| Directory: | ./ |
|---|---|
| File: | storage/innobase/handler/ha_innodb.cc |
| Date: | 2022-12-13 11:44:05 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 8733 | 10087 | 86.6% |
| Branches: | 8470 | 15110 | 56.1% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /***************************************************************************** | ||
| 2 | |||
| 3 | Copyright (c) 2000, 2022, Oracle and/or its affiliates. | ||
| 4 | Copyright (c) 2008, 2009 Google Inc. | ||
| 5 | Copyright (c) 2009, Percona Inc. | ||
| 6 | Copyright (c) 2012, Facebook Inc. | ||
| 7 | |||
| 8 | Portions of this file contain modifications contributed and copyrighted by | ||
| 9 | Google, Inc. Those modifications are gratefully acknowledged and are described | ||
| 10 | briefly in the InnoDB documentation. The contributions by Google are | ||
| 11 | incorporated with their permission, and subject to the conditions contained in | ||
| 12 | the file COPYING.Google. | ||
| 13 | |||
| 14 | Portions of this file contain modifications contributed and copyrighted | ||
| 15 | by Percona Inc.. Those modifications are | ||
| 16 | gratefully acknowledged and are described briefly in the InnoDB | ||
| 17 | documentation. The contributions by Percona Inc. are incorporated with | ||
| 18 | their permission, and subject to the conditions contained in the file | ||
| 19 | COPYING.Percona. | ||
| 20 | |||
| 21 | This program is free software; you can redistribute it and/or modify it under | ||
| 22 | the terms of the GNU General Public License, version 2.0, as published by the | ||
| 23 | Free Software Foundation. | ||
| 24 | |||
| 25 | This program is also distributed with certain software (including but not | ||
| 26 | limited to OpenSSL) that is licensed under separate terms, as designated in a | ||
| 27 | particular file or component or in included license documentation. The authors | ||
| 28 | of MySQL hereby grant you an additional permission to link the program and | ||
| 29 | your derivative works with the separately licensed software that they have | ||
| 30 | included with MySQL. | ||
| 31 | |||
| 32 | This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 33 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
| 34 | FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, | ||
| 35 | for more details. | ||
| 36 | |||
| 37 | You should have received a copy of the GNU General Public License along with | ||
| 38 | this program; if not, write to the Free Software Foundation, Inc., | ||
| 39 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 40 | |||
| 41 | *****************************************************************************/ | ||
| 42 | |||
| 43 | /** @file ha_innodb.cc */ | ||
| 44 | |||
| 45 | #ifndef UNIV_HOTBACKUP | ||
| 46 | #include "my_config.h" | ||
| 47 | #endif /* !UNIV_HOTBACKUP */ | ||
| 48 | |||
| 49 | #include <auto_thd.h> | ||
| 50 | #include <errno.h> | ||
| 51 | #include <fcntl.h> | ||
| 52 | #include <gstream.h> | ||
| 53 | #include <limits.h> | ||
| 54 | #include <log.h> | ||
| 55 | #include <math.h> | ||
| 56 | #include <my_compare.h> | ||
| 57 | #include <mysqld.h> | ||
| 58 | #include <stdlib.h> | ||
| 59 | #include <strfunc.h> | ||
| 60 | #include <time.h> | ||
| 61 | |||
| 62 | #include <algorithm> | ||
| 63 | |||
| 64 | #include <sql_table.h> | ||
| 65 | #include "mysql/components/services/system_variable_source.h" | ||
| 66 | |||
| 67 | #ifndef UNIV_HOTBACKUP | ||
| 68 | #include <current_thd.h> | ||
| 69 | #include <debug_sync.h> | ||
| 70 | #include <derror.h> | ||
| 71 | #include <my_bitmap.h> | ||
| 72 | #include <my_check_opt.h> | ||
| 73 | #include <mysql/service_thd_alloc.h> | ||
| 74 | #include <mysql/service_thd_wait.h> | ||
| 75 | #include <mysql_com.h> | ||
| 76 | #include <sql_acl.h> | ||
| 77 | #include <sql_class.h> | ||
| 78 | #include <sql_show.h> | ||
| 79 | #include <sql_tablespace.h> | ||
| 80 | #include <sql_thd_internal_api.h> | ||
| 81 | #include <sys_vars_shared.h> | ||
| 82 | #include "api0api.h" | ||
| 83 | #include "api0misc.h" | ||
| 84 | #include "arch0arch.h" | ||
| 85 | #include "arch0page.h" | ||
| 86 | #include "auth_acls.h" | ||
| 87 | #include "btr0btr.h" | ||
| 88 | #include "btr0cur.h" | ||
| 89 | #include "btr0sea.h" | ||
| 90 | #include "buf0dblwr.h" | ||
| 91 | #include "buf0dump.h" | ||
| 92 | #include "buf0flu.h" | ||
| 93 | #include "buf0lru.h" | ||
| 94 | #include "buf0stats.h" | ||
| 95 | #include "clone0api.h" | ||
| 96 | #include "clone0clone.h" | ||
| 97 | #include "dd/dd.h" | ||
| 98 | #include "dd/dictionary.h" | ||
| 99 | #include "dd/impl/bootstrap/bootstrap_ctx.h" | ||
| 100 | #include "dd/properties.h" | ||
| 101 | #include "dd/types/index.h" | ||
| 102 | #include "dd/types/object_table.h" | ||
| 103 | #include "dd/types/object_table_definition.h" | ||
| 104 | #include "dd/types/partition.h" | ||
| 105 | #include "dd/types/table.h" | ||
| 106 | #include "dd/types/tablespace.h" | ||
| 107 | #include "ddl0ddl.h" | ||
| 108 | #include "dict0boot.h" | ||
| 109 | #include "dict0crea.h" | ||
| 110 | #include "dict0dd.h" | ||
| 111 | #include "dict0dict.h" | ||
| 112 | #include "dict0load.h" | ||
| 113 | #include "dict0stats.h" | ||
| 114 | #include "dict0stats_bg.h" | ||
| 115 | #include "fil0crypt.h" | ||
| 116 | #include "fil0fil.h" | ||
| 117 | #include "fsp0fsp.h" | ||
| 118 | #include "fsp0space.h" | ||
| 119 | #include "fsp0sysspace.h" | ||
| 120 | #include "fts0fts.h" | ||
| 121 | #include "fts0plugin.h" | ||
| 122 | #include "fts0priv.h" | ||
| 123 | #include "fts0tokenize.h" // true_word_char | ||
| 124 | #include "fts0types.h" | ||
| 125 | #include "ha_innodb.h" | ||
| 126 | #include "ha_innopart.h" | ||
| 127 | #include "ha_prototypes.h" | ||
| 128 | #include "i_s.h" | ||
| 129 | #include "ibuf0ibuf.h" | ||
| 130 | #include "lex_string.h" | ||
| 131 | #include "lob0lob.h" | ||
| 132 | #include "lock0lock.h" | ||
| 133 | #include "log0buf.h" | ||
| 134 | #include "log0chkp.h" | ||
| 135 | #include "log0encryption.h" | ||
| 136 | #include "log0meb.h" | ||
| 137 | #include "log0pfs.h" | ||
| 138 | #include "log0pre_8_0_30.h" | ||
| 139 | #include "log0write.h" | ||
| 140 | #include "mem0mem.h" | ||
| 141 | #include "mtr0mtr.h" | ||
| 142 | #include "my_compare.h" | ||
| 143 | #include "my_compiler.h" | ||
| 144 | #include "my_dbug.h" | ||
| 145 | #include "my_double2ulonglong.h" | ||
| 146 | #include "my_io.h" | ||
| 147 | #include "my_macros.h" | ||
| 148 | #include "my_psi_config.h" | ||
| 149 | #include "mysql/components/services/log_builtins.h" | ||
| 150 | #include "mysql/plugin.h" | ||
| 151 | #include "mysql/psi/mysql_data_lock.h" | ||
| 152 | #include "mysys_err.h" | ||
| 153 | #include "os0thread-create.h" | ||
| 154 | #include "os0thread.h" | ||
| 155 | #include "p_s.h" | ||
| 156 | #include "page0zip.h" | ||
| 157 | #include "pars0pars.h" | ||
| 158 | #include "rem0types.h" | ||
| 159 | #include "row0ext.h" | ||
| 160 | #include "row0import.h" | ||
| 161 | #include "row0ins.h" | ||
| 162 | #include "row0mysql.h" | ||
| 163 | #include "row0quiesce.h" | ||
| 164 | #include "row0sel.h" | ||
| 165 | #include "row0upd.h" | ||
| 166 | #include "sql/plugin_table.h" | ||
| 167 | #include "srv0mon.h" | ||
| 168 | #include "srv0srv.h" | ||
| 169 | #include "srv0start.h" | ||
| 170 | #include "sync0sync.h" | ||
| 171 | #ifdef UNIV_DEBUG | ||
| 172 | #include "trx0purge.h" | ||
| 173 | #endif /* UNIV_DEBUG */ | ||
| 174 | #include "dict0priv.h" | ||
| 175 | #include "dict0sdi.h" | ||
| 176 | #include "dict0upgrade.h" | ||
| 177 | #include "os0thread-create.h" | ||
| 178 | #include "os0thread.h" | ||
| 179 | #include "sql/auth/auth_common.h" | ||
| 180 | #include "sql/item.h" | ||
| 181 | #include "sql_base.h" | ||
| 182 | #include "srv0tmp.h" | ||
| 183 | #include "trx0rec.h" | ||
| 184 | #include "trx0roll.h" | ||
| 185 | #include "trx0rseg.h" | ||
| 186 | #include "trx0sys.h" | ||
| 187 | #include "trx0trx.h" | ||
| 188 | #include "trx0xa.h" | ||
| 189 | #include "ut0mem.h" | ||
| 190 | #include "ut0test.h" | ||
| 191 | #include "xtradb_i_s.h" | ||
| 192 | #else | ||
| 193 | #include <typelib.h> | ||
| 194 | #include "buf0types.h" | ||
| 195 | #include "univ.i" | ||
| 196 | #endif /* !UNIV_HOTBACKUP */ | ||
| 197 | |||
| 198 | #include "log0files_io.h" | ||
| 199 | |||
| 200 | #include "sql-common/json_binary.h" | ||
| 201 | #include "sql-common/json_dom.h" | ||
| 202 | |||
| 203 | #ifdef WITH_WSREP | ||
| 204 | #include "my_md5.h" | ||
| 205 | #include "tc_log.h" | ||
| 206 | #include "wsrep_api.h" | ||
| 207 | #include "wsrep_mysqld.h" | ||
| 208 | |||
| 209 | /* Must always init to false. */ | ||
| 210 | static bool innobase_disallow_writes = false; | ||
| 211 | |||
| 212 | extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key, | ||
| 213 | size_t cache_key_len, | ||
| 214 | const uchar *row_id, size_t row_id_len, | ||
| 215 | wsrep_buf_t *key, size_t *key_len); | ||
| 216 | #endif /* WITH_WSREP */ | ||
| 217 | |||
| 218 | #include "os0enc.h" | ||
| 219 | #include "os0file.h" | ||
| 220 | |||
| 221 | #include <mutex> | ||
| 222 | #include <sstream> | ||
| 223 | #include <string> | ||
| 224 | #include <vector> | ||
| 225 | |||
| 226 | #ifdef HAVE_UNISTD_H | ||
| 227 | #include <unistd.h> | ||
| 228 | #endif /* HAVE_UNISTD_H */ | ||
| 229 | |||
| 230 | #ifndef UNIV_HOTBACKUP | ||
| 231 | |||
| 232 | namespace innobase { | ||
| 233 | namespace component_services { | ||
| 234 | SERVICE_TYPE(registry) *reg_srv = nullptr; | ||
| 235 | |||
| 236 | /** Initialize component service handles */ | ||
| 237 | 9726 | static bool intitialize_service_handles() { | |
| 238 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | DBUG_TRACE; |
| 239 | |||
| 240 | ✗ | auto cleanup = [&]() { | |
| 241 | /* Add module specific deinitialization here */ | ||
| 242 | ✗ | innobase::encryption::deinit_keyring_services(reg_srv); | |
| 243 | ✗ | mysql_plugin_registry_release(reg_srv); | |
| 244 | ✗ | }; | |
| 245 | |||
| 246 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | reg_srv = mysql_plugin_registry_acquire(); |
| 247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (reg_srv == nullptr) { |
| 248 | ✗ | return false; | |
| 249 | } | ||
| 250 | |||
| 251 | /* Add module specific initialization here */ | ||
| 252 |
2/4✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
|
9726 | if (innobase::encryption::init_keyring_services(reg_srv) == false) { |
| 253 | ✗ | cleanup(); | |
| 254 | ✗ | return false; | |
| 255 | } | ||
| 256 | |||
| 257 | /* During initialize, PFS is not ready. */ | ||
| 258 |
3/4✓ Branch 0 taken 9516 times.
✓ Branch 1 taken 210 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
|
19242 | if (!opt_initialize && |
| 259 |
2/4✓ Branch 0 taken 9516 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9516 times.
|
9516 | !log_pfs_acquire_services(innobase::component_services::reg_srv)) { |
| 260 | ✗ | ib::warn(ER_IB_MSG_LOG_PFS_ACQUIRE_SERVICES_FAILED); | |
| 261 | } | ||
| 262 | |||
| 263 | 9726 | return true; | |
| 264 | 9726 | } | |
| 265 | |||
| 266 | /** Deinitialize compoent service handles */ | ||
| 267 | 8462 | static void deinitialize_service_handles() { | |
| 268 |
1/2✓ Branch 0 taken 8462 times.
✗ Branch 1 not taken.
|
8462 | DBUG_TRACE; |
| 269 |
2/2✓ Branch 0 taken 8248 times.
✓ Branch 1 taken 214 times.
|
8462 | if (!opt_initialize) { |
| 270 |
1/2✓ Branch 0 taken 8248 times.
✗ Branch 1 not taken.
|
8248 | log_pfs_release_services(reg_srv); |
| 271 | } | ||
| 272 |
1/2✓ Branch 0 taken 8462 times.
✗ Branch 1 not taken.
|
8462 | innobase::encryption::deinit_keyring_services(reg_srv); |
| 273 |
2/2✓ Branch 0 taken 8454 times.
✓ Branch 1 taken 8 times.
|
8462 | if (reg_srv != nullptr) { |
| 274 |
1/2✓ Branch 0 taken 8454 times.
✗ Branch 1 not taken.
|
8454 | mysql_plugin_registry_release(reg_srv); |
| 275 | } | ||
| 276 | 8462 | } | |
| 277 | |||
| 278 | } // namespace component_services | ||
| 279 | } // namespace innobase | ||
| 280 | |||
| 281 | /** Stop printing warnings, if the count exceeds this threshold. */ | ||
| 282 | static const size_t MOVED_FILES_PRINT_THRESHOLD = 32; | ||
| 283 | |||
| 284 | SERVICE_TYPE(registry) * reg_svc; | ||
| 285 | SERVICE_TYPE(system_variable_source) * sysvar_source_svc; | ||
| 286 | SERVICE_TYPE(clone_protocol) * clone_protocol_svc; | ||
| 287 | |||
| 288 | static const uint64_t KB = 1024; | ||
| 289 | static const uint64_t MB = KB * 1024; | ||
| 290 | static const uint64_t GB = MB * 1024; | ||
| 291 | |||
| 292 | /** fil_space_t::flags for hard-coded tablespaces */ | ||
| 293 | uint32_t predefined_flags; | ||
| 294 | |||
| 295 | /** to protect innobase_open_files */ | ||
| 296 | static mysql_mutex_t innobase_share_mutex; | ||
| 297 | |||
| 298 | /* mutex protecting the master_key_id change. */ | ||
| 299 | ib_mutex_t master_key_id_mutex; | ||
| 300 | |||
| 301 | /** to force correct commit order in binlog */ | ||
| 302 | static ulong commit_threads = 0; | ||
| 303 | static mysql_cond_t commit_cond; | ||
| 304 | static mysql_mutex_t commit_cond_m; | ||
| 305 | mysql_cond_t resume_encryption_cond; | ||
| 306 | mysql_mutex_t resume_encryption_cond_m; | ||
| 307 | bool innodb_inited = false; | ||
| 308 | |||
| 309 | 3699883976 | [[maybe_unused]] static inline bool EQ_CURRENT_THD(THD *thd) { | |
| 310 | 3699883976 | return thd == current_thd; | |
| 311 | } | ||
| 312 | |||
| 313 | static struct handlerton *innodb_hton_ptr; | ||
| 314 | |||
| 315 | static const long AUTOINC_OLD_STYLE_LOCKING = 0; | ||
| 316 | static const long AUTOINC_NEW_STYLE_LOCKING = 1; | ||
| 317 | static const long AUTOINC_NO_LOCKING = 2; | ||
| 318 | |||
| 319 | static long innobase_open_files; | ||
| 320 | static long innobase_autoinc_lock_mode; | ||
| 321 | static ulong innobase_commit_concurrency = 0; | ||
| 322 | |||
| 323 | /* Boolean @@innodb_buffer_pool_in_core_file. */ | ||
| 324 | bool srv_buffer_pool_in_core_file = true; | ||
| 325 | |||
| 326 | /** Percentage of the buffer pool to reserve for 'old' blocks. | ||
| 327 | Connected to buf_LRU_old_ratio. */ | ||
| 328 | static uint innobase_old_blocks_pct; | ||
| 329 | |||
| 330 | /* The default values for the following char* start-up parameters | ||
| 331 | are determined in innodb_init_params(). */ | ||
| 332 | |||
| 333 | static char *innobase_data_home_dir = nullptr; | ||
| 334 | static char *innobase_data_file_path = nullptr; | ||
| 335 | static char *innobase_temp_data_file_path = nullptr; | ||
| 336 | static char *innobase_enable_monitor_counter = nullptr; | ||
| 337 | static char *innobase_disable_monitor_counter = nullptr; | ||
| 338 | static char *innobase_reset_monitor_counter = nullptr; | ||
| 339 | static char *innobase_reset_all_monitor_counter = nullptr; | ||
| 340 | static char *innobase_doublewrite_dir = nullptr; | ||
| 341 | |||
| 342 | static ulong innodb_flush_method; | ||
| 343 | |||
| 344 | /* This variable can be set in the server configure file, specifying | ||
| 345 | stopword table to be used */ | ||
| 346 | static char *innobase_server_stopword_table = nullptr; | ||
| 347 | |||
| 348 | /* Below we have boolean-valued start-up parameters, and their default | ||
| 349 | values */ | ||
| 350 | |||
| 351 | static bool innobase_rollback_on_timeout = false; | ||
| 352 | static bool innobase_create_status_file = false; | ||
| 353 | bool innobase_stats_on_metadata = true; | ||
| 354 | static bool innodb_optimize_fulltext_only = false; | ||
| 355 | |||
| 356 | static char *innodb_version_str = (char *)INNODB_VERSION_STR; | ||
| 357 | |||
| 358 | static Innodb_data_lock_inspector innodb_data_lock_inspector; | ||
| 359 | |||
| 360 | static const uint MAX_ENCRYPTION_THREADS = 255; | ||
| 361 | extern uint srv_fil_crypt_rotate_key_age; | ||
| 362 | extern uint srv_n_fil_crypt_iops; | ||
| 363 | |||
| 364 | /** Path to the Percona-specific parallel doublewrite buffer (Deprecated) */ | ||
| 365 | static char *srv_parallel_doublewrite_path_deprecated = nullptr; | ||
| 366 | |||
| 367 | /** Enable or disable encryption of pages in parallel doublewrite buffer | ||
| 368 | file (Deprecated) */ | ||
| 369 | static bool srv_parallel_dblwr_encrypt_deprecated = false; | ||
| 370 | |||
| 371 | /** Note we cannot use rec_format_enum because we do not allow | ||
| 372 | COMPRESSED row format for innodb_default_row_format option. */ | ||
| 373 | enum default_row_format_enum { | ||
| 374 | DEFAULT_ROW_FORMAT_REDUNDANT = 0, | ||
| 375 | DEFAULT_ROW_FORMAT_COMPACT = 1, | ||
| 376 | DEFAULT_ROW_FORMAT_DYNAMIC = 2, | ||
| 377 | }; | ||
| 378 | |||
| 379 | #if defined(_WIN32) || defined(_WIN64) | ||
| 380 | #include <Windows.h> | ||
| 381 | static double get_mem_GlobalMemoryStatus() { | ||
| 382 | MEMORYSTATUSEX ms; | ||
| 383 | ms.dwLength = sizeof(ms); | ||
| 384 | GlobalMemoryStatusEx(&ms); | ||
| 385 | return (((double)ms.ullTotalPhys) / GB); | ||
| 386 | } | ||
| 387 | #undef get_sys_mem | ||
| 388 | #define get_sys_mem get_mem_GlobalMemoryStatus | ||
| 389 | #else | ||
| 390 | ✗ | static double get_mem_sysconf() { | |
| 391 | ✗ | return (((double)sysconf(_SC_PHYS_PAGES)) * | |
| 392 | ✗ | ((double)sysconf(_SC_PAGESIZE) / GB)); | |
| 393 | } | ||
| 394 | #undef get_sys_mem | ||
| 395 | #define get_sys_mem get_mem_sysconf | ||
| 396 | #endif /* defined(_WIN32) || defined(_WIN64) */ | ||
| 397 | |||
| 398 | /** Release all acquired services from mysql server. */ | ||
| 399 | 8462 | static void release_plugin_services() { | |
| 400 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 8378 times.
|
8462 | if (reg_svc == nullptr) { |
| 401 | 84 | return; | |
| 402 | } | ||
| 403 | |||
| 404 |
1/2✓ Branch 0 taken 8378 times.
✗ Branch 1 not taken.
|
8378 | if (sysvar_source_svc != nullptr) { |
| 405 | using sysvar_source_svc_t = SERVICE_TYPE_NO_CONST(system_variable_source); | ||
| 406 | 8378 | reg_svc->release(reinterpret_cast<my_h_service>( | |
| 407 | const_cast<sysvar_source_svc_t *>(sysvar_source_svc))); | ||
| 408 | 8378 | sysvar_source_svc = nullptr; | |
| 409 | } | ||
| 410 | |||
| 411 |
1/2✓ Branch 0 taken 8378 times.
✗ Branch 1 not taken.
|
8378 | if (clone_protocol_svc != nullptr) { |
| 412 | using clone_protocol_t = SERVICE_TYPE_NO_CONST(clone_protocol); | ||
| 413 | 8378 | reg_svc->release(reinterpret_cast<my_h_service>( | |
| 414 | const_cast<clone_protocol_t *>(clone_protocol_svc))); | ||
| 415 | 8378 | clone_protocol_svc = nullptr; | |
| 416 | } | ||
| 417 | |||
| 418 | /* Release registry service */ | ||
| 419 | 8378 | mysql_plugin_registry_release(reg_svc); | |
| 420 | 8378 | reg_svc = nullptr; | |
| 421 | } | ||
| 422 | |||
| 423 | /** Acquire required services from mysql server. */ | ||
| 424 | 9734 | static void acquire_plugin_services() { | |
| 425 | /* Acquire mysql_server's registry service */ | ||
| 426 |
1/2✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
|
9734 | reg_svc = mysql_plugin_registry_acquire(); |
| 427 | |||
| 428 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9734 times.
|
9734 | if (reg_svc == nullptr) { |
| 429 | ✗ | ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "plugin registry"); | |
| 430 | ✗ | return; | |
| 431 | } | ||
| 432 | |||
| 433 | my_h_service service; | ||
| 434 | |||
| 435 | /* Acquire system_variable_source service */ | ||
| 436 |
2/4✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9734 times.
|
9734 | if (reg_svc->acquire("system_variable_source", &service)) { |
| 437 | ✗ | ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "system_variable_source"); | |
| 438 | |||
| 439 | } else { | ||
| 440 | 9734 | sysvar_source_svc = | |
| 441 | reinterpret_cast<SERVICE_TYPE(system_variable_source) *>(service); | ||
| 442 | } | ||
| 443 | |||
| 444 | /* Acquire clone protocol service handle. */ | ||
| 445 |
2/4✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9734 times.
|
9734 | if (reg_svc->acquire("clone_protocol", &service)) { |
| 446 | ✗ | ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "clone_protocol"); | |
| 447 | |||
| 448 | } else { | ||
| 449 | 9734 | clone_protocol_svc = | |
| 450 | reinterpret_cast<SERVICE_TYPE(clone_protocol) *>(service); | ||
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | /** Return the InnoDB ROW_FORMAT enum value | ||
| 455 | @param[in] row_format row_format from "innodb_default_row_format" | ||
| 456 | @return InnoDB ROW_FORMAT value from rec_format_t enum. */ | ||
| 457 | 395987 | static rec_format_t get_row_format(ulong row_format) { | |
| 458 |
3/4✓ Branch 0 taken 27 times.
✓ Branch 1 taken 225 times.
✓ Branch 2 taken 395735 times.
✗ Branch 3 not taken.
|
395987 | switch (row_format) { |
| 459 | 27 | case DEFAULT_ROW_FORMAT_REDUNDANT: | |
| 460 | 27 | return (REC_FORMAT_REDUNDANT); | |
| 461 | 225 | case DEFAULT_ROW_FORMAT_COMPACT: | |
| 462 | 225 | return (REC_FORMAT_COMPACT); | |
| 463 | 395735 | case DEFAULT_ROW_FORMAT_DYNAMIC: | |
| 464 | 395735 | return (REC_FORMAT_DYNAMIC); | |
| 465 | ✗ | default: | |
| 466 | ✗ | ut_d(ut_error); | |
| 467 | ut_o(return (REC_FORMAT_DYNAMIC)); | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | /** Note that a transaction has been deregistered. | ||
| 472 | @param[in] trx transaction */ | ||
| 473 | static void trx_deregister_from_2pc(trx_t *trx); | ||
| 474 | static ulong innodb_default_row_format = DEFAULT_ROW_FORMAT_DYNAMIC; | ||
| 475 | |||
| 476 | #ifdef UNIV_DEBUG | ||
| 477 | /** Values for --innodb-debug-compress names. */ | ||
| 478 | static const char *innodb_debug_compress_names[] = {"none", "zlib", "lz4", | ||
| 479 | "lz4hc", NullS}; | ||
| 480 | |||
| 481 | /** Enumeration of --innodb-debug-compress */ | ||
| 482 | static TYPELIB innodb_debug_compress_typelib = { | ||
| 483 | array_elements(innodb_debug_compress_names) - 1, | ||
| 484 | "innodb_debug_compress_typelib", innodb_debug_compress_names, nullptr}; | ||
| 485 | #endif /* UNIV_DEBUG */ | ||
| 486 | |||
| 487 | /** Possible values for system variable "innodb_stats_method". The values | ||
| 488 | are defined the same as its corresponding MyISAM system variable | ||
| 489 | "myisam_stats_method"(see "myisam_stats_method_names"), for better usability */ | ||
| 490 | static const char *innodb_stats_method_names[] = { | ||
| 491 | "nulls_equal", "nulls_unequal", "nulls_ignored", NullS}; | ||
| 492 | |||
| 493 | /** Used to define an enumerate type of the system variable innodb_stats_method. | ||
| 494 | This is the same as "myisam_stats_method_typelib" */ | ||
| 495 | static TYPELIB innodb_stats_method_typelib = { | ||
| 496 | array_elements(innodb_stats_method_names) - 1, | ||
| 497 | "innodb_stats_method_typelib", innodb_stats_method_names, nullptr}; | ||
| 498 | |||
| 499 | #endif /* UNIV_HOTBACKUP */ | ||
| 500 | |||
| 501 | /** Possible values of the parameter innodb_checksum_algorithm */ | ||
| 502 | static const char *innodb_checksum_algorithm_names[] = { | ||
| 503 | "crc32", "strict_crc32", "innodb", "strict_innodb", | ||
| 504 | "none", "strict_none", NullS}; | ||
| 505 | |||
| 506 | /** Used to define an enumerate type of the system variable | ||
| 507 | innodb_checksum_algorithm. */ | ||
| 508 | static TYPELIB innodb_checksum_algorithm_typelib = { | ||
| 509 | array_elements(innodb_checksum_algorithm_names) - 1, | ||
| 510 | "innodb_checksum_algorithm_typelib", innodb_checksum_algorithm_names, | ||
| 511 | nullptr}; | ||
| 512 | |||
| 513 | #ifndef UNIV_HOTBACKUP | ||
| 514 | /** Names of allowed values of innodb_flush_method */ | ||
| 515 | static const char *innodb_flush_method_names[] = { | ||
| 516 | #ifndef _WIN32 /* See srv_unix_flush_t */ | ||
| 517 | "fsync", "O_DSYNC", "littlesync", "nosync", "O_DIRECT", "O_DIRECT_NO_FSYNC", | ||
| 518 | #else /* _WIN32; see srv_win_flush_t */ | ||
| 519 | "unbuffered", "normal", | ||
| 520 | #endif | ||
| 521 | NullS}; | ||
| 522 | |||
| 523 | /** Enumeration of innodb_flush_method */ | ||
| 524 | static TYPELIB innodb_flush_method_typelib = { | ||
| 525 | array_elements(innodb_flush_method_names) - 1, | ||
| 526 | "innodb_flush_method_typelib", innodb_flush_method_names, nullptr}; | ||
| 527 | |||
| 528 | /** Possible values for system variable "innodb_cleaner_lsn_age_factor". */ | ||
| 529 | static const char *innodb_cleaner_lsn_age_factor_names[] = { | ||
| 530 | "legacy", "high_checkpoint", NullS}; | ||
| 531 | |||
| 532 | /** Enumeration for innodb_cleaner_lsn_age_factor. */ | ||
| 533 | static TYPELIB innodb_cleaner_lsn_age_factor_typelib = { | ||
| 534 | array_elements(innodb_cleaner_lsn_age_factor_names) - 1, | ||
| 535 | "innodb_cleaner_lsn_age_factor_typelib", | ||
| 536 | innodb_cleaner_lsn_age_factor_names, nullptr}; | ||
| 537 | |||
| 538 | /** Possible values for system variable "innodb_empty_free_list_algorithm". */ | ||
| 539 | static const char *innodb_empty_free_list_algorithm_names[] = { | ||
| 540 | "legacy", "backoff", NullS}; | ||
| 541 | |||
| 542 | /** Enumeration for innodb_empty_free_list_algorithm. */ | ||
| 543 | static TYPELIB innodb_empty_free_list_algorithm_typelib = { | ||
| 544 | array_elements(innodb_empty_free_list_algorithm_names) - 1, | ||
| 545 | "innodb_empty_free_list_algorithm_typelib", | ||
| 546 | innodb_empty_free_list_algorithm_names, nullptr}; | ||
| 547 | |||
| 548 | /** Possible values for system variable "innodb_default_row_format". */ | ||
| 549 | static const char *innodb_default_row_format_names[] = {"redundant", "compact", | ||
| 550 | "dynamic", NullS}; | ||
| 551 | |||
| 552 | /** Used to define an enumerate type of the system variable | ||
| 553 | innodb_default_row_format. */ | ||
| 554 | static TYPELIB innodb_default_row_format_typelib = { | ||
| 555 | array_elements(innodb_default_row_format_names) - 1, | ||
| 556 | "innodb_default_row_format_typelib", innodb_default_row_format_names, | ||
| 557 | nullptr}; | ||
| 558 | |||
| 559 | /** Possible values for system variable "innodb_doublewrite". | ||
| 560 | @note: If you change order or add new values, please update dblwr::mode_t. */ | ||
| 561 | static const char *innodb_doublewrite_names[] = { | ||
| 562 | "OFF", "ON", "DETECT_ONLY", "DETECT_AND_RECOVER", "FALSE", "TRUE", NullS}; | ||
| 563 | |||
| 564 | /** Used to define an enumerate type of the system variable | ||
| 565 | innodb_default_row_format. */ | ||
| 566 | static TYPELIB innodb_doublewrite_typelib = { | ||
| 567 | array_elements(innodb_doublewrite_names) - 1, "innodb_doublewrite_typelib", | ||
| 568 | innodb_doublewrite_names, nullptr}; | ||
| 569 | |||
| 570 | #else /* !UNIV_HOTBACKUP */ | ||
| 571 | |||
| 572 | /** Returns the name of the checksum algorithm corresponding to the | ||
| 573 | algorithm id given by "algo_enum" parameter. | ||
| 574 | @param[in] algo_enum algorithm enumerator | ||
| 575 | @return C-string algorithm name */ | ||
| 576 | const char *meb_get_checksum_algorithm_name( | ||
| 577 | srv_checksum_algorithm_t algo_enum) { | ||
| 578 | return (get_type(&innodb_checksum_algorithm_typelib, algo_enum)); | ||
| 579 | } | ||
| 580 | |||
| 581 | /** Retrieves the enum corresponding to the checksum algorithm | ||
| 582 | name specified by algo_name. If the call succeeds, returns | ||
| 583 | true and checksum algorithm enum is returned in algo_enum. | ||
| 584 | @param[in] algo_name algorithm name | ||
| 585 | @param[out] algo_enum algorithm enumerator | ||
| 586 | @retval true if successful | ||
| 587 | @retval false if algorithn name not found */ | ||
| 588 | bool meb_get_checksum_algorithm_enum(const char *algo_name, | ||
| 589 | srv_checksum_algorithm_t &algo_enum) { | ||
| 590 | int type = | ||
| 591 | find_type(algo_name, &innodb_checksum_algorithm_typelib, FIND_TYPE_BASIC); | ||
| 592 | if (type <= 0) { | ||
| 593 | /** Invalid algorithm name */ | ||
| 594 | return false; | ||
| 595 | } else { | ||
| 596 | algo_enum = srv_checksum_algorithm_t(type - 1); | ||
| 597 | } | ||
| 598 | |||
| 599 | return true; | ||
| 600 | } | ||
| 601 | #endif /* !UNIV_HOTBACKUP */ | ||
| 602 | |||
| 603 | static const char *sys_tablespace_encrypt_names[] = { | ||
| 604 | "OFF", "ON", "RE_ENCRYPTING_TO_KEYRING", NullS}; | ||
| 605 | static TYPELIB sys_tablespace_encrypt_typelib = { | ||
| 606 | array_elements(sys_tablespace_encrypt_names) - 1, | ||
| 607 | "sys_tablespace_encrypt_typelib", sys_tablespace_encrypt_names, nullptr}; | ||
| 608 | |||
| 609 | #ifndef UNIV_HOTBACKUP | ||
| 610 | /* The following counter is used to convey information to InnoDB | ||
| 611 | about server activity: in case of normal DML ops it is not | ||
| 612 | sensible to call srv_active_wake_master_thread after each | ||
| 613 | operation, we only do it every INNOBASE_WAKE_INTERVAL'th step. */ | ||
| 614 | |||
| 615 | constexpr uint32_t INNOBASE_WAKE_INTERVAL = 32; | ||
| 616 | static ulong innobase_active_counter = 0; | ||
| 617 | |||
| 618 | static hash_table_t *innobase_open_tables; | ||
| 619 | |||
| 620 | /** Array of data files of the system tablespace */ | ||
| 621 | static std::vector<Plugin_tablespace::Plugin_tablespace_file *, | ||
| 622 | ut::allocator<Plugin_tablespace::Plugin_tablespace_file *>> | ||
| 623 | innobase_sys_files; | ||
| 624 | |||
| 625 | /** Allowed values of innodb_change_buffering */ | ||
| 626 | static const char *innodb_change_buffering_names[] = { | ||
| 627 | "none", /* IBUF_USE_NONE */ | ||
| 628 | "inserts", /* IBUF_USE_INSERT */ | ||
| 629 | "deletes", /* IBUF_USE_DELETE_MARK */ | ||
| 630 | "changes", /* IBUF_USE_INSERT_DELETE_MARK */ | ||
| 631 | "purges", /* IBUF_USE_DELETE */ | ||
| 632 | "all", /* IBUF_USE_ALL */ | ||
| 633 | NullS}; | ||
| 634 | |||
| 635 | /** Enumeration of innodb_change_buffering */ | ||
| 636 | static TYPELIB innodb_change_buffering_typelib = { | ||
| 637 | array_elements(innodb_change_buffering_names) - 1, | ||
| 638 | "innodb_change_buffering_typelib", innodb_change_buffering_names, nullptr}; | ||
| 639 | |||
| 640 | /** Retrieve the FTS Relevance Ranking result for doc with doc_id | ||
| 641 | of m_prebuilt->fts_doc_id | ||
| 642 | @param[in,out] fts_hdl FTS handler | ||
| 643 | @return the relevance ranking value */ | ||
| 644 | static float innobase_fts_retrieve_ranking(FT_INFO *fts_hdl); | ||
| 645 | /** Free the memory for the FTS handler | ||
| 646 | @param[in,out] fts_hdl FTS handler */ | ||
| 647 | static void innobase_fts_close_ranking(FT_INFO *fts_hdl); | ||
| 648 | |||
| 649 | /** Find and Retrieve the FTS Relevance Ranking result for doc with doc_id | ||
| 650 | of m_prebuilt->fts_doc_id | ||
| 651 | @param[in,out] fts_hdl FTS handler | ||
| 652 | @return the relevance ranking value */ | ||
| 653 | static float innobase_fts_find_ranking(FT_INFO *fts_hdl, uchar *, uint); | ||
| 654 | |||
| 655 | /* Call back function array defined by MySQL and used to | ||
| 656 | retrieve FTS results. */ | ||
| 657 | const struct _ft_vft ft_vft_result = {nullptr, innobase_fts_find_ranking, | ||
| 658 | innobase_fts_close_ranking, | ||
| 659 | innobase_fts_retrieve_ranking, nullptr}; | ||
| 660 | |||
| 661 | /** @return version of the extended FTS API */ | ||
| 662 | ✗ | static uint innobase_fts_get_version() { | |
| 663 | /* Currently this doesn't make much sense as returning | ||
| 664 | HA_CAN_FULLTEXT_EXT automatically mean this version is supported. | ||
| 665 | This supposed to ease future extensions. */ | ||
| 666 | ✗ | return (2); | |
| 667 | } | ||
| 668 | |||
| 669 | /** @return Which part of the extended FTS API is supported */ | ||
| 670 | 163 | static ulonglong innobase_fts_flags() { | |
| 671 | 163 | return (FTS_ORDERED_RESULT | FTS_DOCID_IN_RESULT); | |
| 672 | } | ||
| 673 | |||
| 674 | /** Find and Retrieve the FTS doc_id for the current result row | ||
| 675 | @param[in,out] fts_hdl FTS handler | ||
| 676 | @return the document ID */ | ||
| 677 | static ulonglong innobase_fts_retrieve_docid(FT_INFO_EXT *fts_hdl); | ||
| 678 | |||
| 679 | /** Find and retrieve the size of the current result | ||
| 680 | @param[in,out] fts_hdl FTS handler | ||
| 681 | @return number of matching rows */ | ||
| 682 | 152 | static ulonglong innobase_fts_count_matches( | |
| 683 | FT_INFO_EXT *fts_hdl) /*!< in: FTS handler */ | ||
| 684 | { | ||
| 685 | 152 | NEW_FT_INFO *handle = reinterpret_cast<NEW_FT_INFO *>(fts_hdl); | |
| 686 | |||
| 687 |
2/2✓ Branch 0 taken 137 times.
✓ Branch 1 taken 15 times.
|
152 | if (handle->ft_result->rankings_by_id != nullptr) { |
| 688 | 137 | return (rbt_size(handle->ft_result->rankings_by_id)); | |
| 689 | } else { | ||
| 690 | 15 | return (0); | |
| 691 | } | ||
| 692 | } | ||
| 693 | |||
| 694 | const struct _ft_vft_ext ft_vft_ext_result = { | ||
| 695 | innobase_fts_get_version, innobase_fts_flags, innobase_fts_retrieve_docid, | ||
| 696 | innobase_fts_count_matches}; | ||
| 697 | |||
| 698 | #ifdef HAVE_PSI_INTERFACE | ||
| 699 | #define PSI_KEY(n, flag, volatility, doc) \ | ||
| 700 | { &(n##_key.m_value), #n, flag, volatility, doc } | ||
| 701 | #define PSI_MEMORY_KEY(n, flag, volatility, doc) \ | ||
| 702 | { &(n##_key), #n, flag, volatility, doc } | ||
| 703 | #define PSI_MUTEX_KEY(n, flag, volatility, doc) \ | ||
| 704 | { &(n##_key.m_value), #n, flag, volatility, doc } | ||
| 705 | /* All RWLOCK used in Innodb are SX-locks */ | ||
| 706 | #define PSI_RWLOCK_KEY(n, volatility, doc) \ | ||
| 707 | { &n##_key.m_value, #n, PSI_FLAG_RWLOCK_SX, volatility, doc } | ||
| 708 | #define PSI_THREAD_KEY(n, osn, flag, volatility, doc) \ | ||
| 709 | { &(n##_key.m_value), #n, osn, flag, volatility, doc } | ||
| 710 | |||
| 711 | /* Keys to register pthread mutexes/cond in the current file with | ||
| 712 | performance schema */ | ||
| 713 | static mysql_pfs_key_t innobase_share_mutex_key; | ||
| 714 | static mysql_pfs_key_t commit_cond_mutex_key; | ||
| 715 | static mysql_pfs_key_t commit_cond_key; | ||
| 716 | mysql_pfs_key_t resume_encryption_cond_mutex_key; | ||
| 717 | mysql_pfs_key_t resume_encryption_cond_key; | ||
| 718 | |||
| 719 | static PSI_mutex_info all_pthread_mutexes[] = { | ||
| 720 | PSI_MUTEX_KEY(commit_cond_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 721 | PSI_MUTEX_KEY(innobase_share_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 722 | PSI_MUTEX_KEY(resume_encryption_cond_mutex, 0, 0, PSI_DOCUMENT_ME)}; | ||
| 723 | |||
| 724 | static PSI_cond_info all_innodb_conds[] = { | ||
| 725 | PSI_KEY(commit_cond, 0, 0, PSI_DOCUMENT_ME), | ||
| 726 | PSI_KEY(resume_encryption_cond, 0, 0, PSI_DOCUMENT_ME)}; | ||
| 727 | |||
| 728 | #ifdef UNIV_PFS_MEMORY | ||
| 729 | /* pfs keys related to memory that is performance schema instrumented | ||
| 730 | when "UNIV_PFS_MEMORY" is defined */ | ||
| 731 | static PSI_memory_info pfs_instrumented_innodb_memory[] = { | ||
| 732 | PSI_MEMORY_KEY(log_buffer_memory, 0, 0, "Redo log buffer")}; | ||
| 733 | #endif /* UNIV_PFS_MEMORY */ | ||
| 734 | |||
| 735 | #ifdef UNIV_PFS_MUTEX | ||
| 736 | /* all_innodb_mutexes array contains mutexes that are | ||
| 737 | performance schema instrumented if "UNIV_PFS_MUTEX" | ||
| 738 | is defined */ | ||
| 739 | static PSI_mutex_info all_innodb_mutexes[] = { | ||
| 740 | PSI_MUTEX_KEY(autoinc_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 741 | PSI_MUTEX_KEY(autoinc_persisted_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 742 | #ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK | ||
| 743 | PSI_MUTEX_KEY(buffer_block_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 744 | #endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */ | ||
| 745 | PSI_MUTEX_KEY(buf_pool_chunks_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 746 | PSI_MUTEX_KEY(buf_pool_flush_state_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 747 | PSI_MUTEX_KEY(buf_pool_LRU_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 748 | PSI_MUTEX_KEY(buf_pool_free_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 749 | PSI_MUTEX_KEY(buf_pool_zip_free_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 750 | PSI_MUTEX_KEY(buf_pool_zip_hash_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 751 | PSI_MUTEX_KEY(buf_pool_zip_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 752 | PSI_MUTEX_KEY(clone_snapshot_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 753 | PSI_MUTEX_KEY(clone_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 754 | PSI_MUTEX_KEY(clone_task_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 755 | PSI_MUTEX_KEY(ddl_autoinc_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 756 | PSI_MUTEX_KEY(dict_foreign_err_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 757 | PSI_MUTEX_KEY(dict_persist_dirty_tables_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 758 | PSI_MUTEX_KEY(dict_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 759 | PSI_MUTEX_KEY(dict_table_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 760 | PSI_MUTEX_KEY(parser_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 761 | PSI_MUTEX_KEY(recalc_pool_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 762 | PSI_MUTEX_KEY(fil_system_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 763 | PSI_MUTEX_KEY(file_open_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 764 | PSI_MUTEX_KEY(flush_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 765 | PSI_MUTEX_KEY(fts_bg_threads_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 766 | PSI_MUTEX_KEY(fts_delete_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 767 | PSI_MUTEX_KEY(fts_optimize_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 768 | PSI_MUTEX_KEY(fts_doc_id_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 769 | PSI_MUTEX_KEY(fts_pll_tokenize_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 770 | PSI_MUTEX_KEY(hash_table_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 771 | PSI_MUTEX_KEY(ibuf_bitmap_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 772 | PSI_MUTEX_KEY(ibuf_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 773 | PSI_MUTEX_KEY(ibuf_pessimistic_insert_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 774 | PSI_MUTEX_KEY(lock_free_hash_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 775 | PSI_MUTEX_KEY(log_limits_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 776 | PSI_MUTEX_KEY(log_files_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 777 | PSI_MUTEX_KEY(log_checkpointer_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 778 | PSI_MUTEX_KEY(log_closer_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 779 | PSI_MUTEX_KEY(log_writer_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 780 | PSI_MUTEX_KEY(log_flusher_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 781 | PSI_MUTEX_KEY(log_write_notifier_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 782 | PSI_MUTEX_KEY(log_flush_notifier_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 783 | PSI_MUTEX_KEY(log_sys_arch_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 784 | PSI_MUTEX_KEY(log_cmdq_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 785 | PSI_MUTEX_KEY(log_sn_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 786 | PSI_MUTEX_KEY(mutex_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 787 | PSI_MUTEX_KEY(page_sys_arch_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 788 | PSI_MUTEX_KEY(page_sys_arch_oper_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 789 | PSI_MUTEX_KEY(page_sys_arch_client_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 790 | PSI_MUTEX_KEY(page_zip_stat_per_index_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 791 | PSI_MUTEX_KEY(page_cleaner_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 792 | PSI_MUTEX_KEY(parallel_read_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 793 | PSI_MUTEX_KEY(dblwr_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 794 | PSI_MUTEX_KEY(purge_sys_pq_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 795 | PSI_MUTEX_KEY(recv_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 796 | PSI_MUTEX_KEY(recv_writer_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 797 | PSI_MUTEX_KEY(temp_space_rseg_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 798 | PSI_MUTEX_KEY(undo_space_rseg_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 799 | PSI_MUTEX_KEY(trx_sys_rseg_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 800 | #ifdef UNIV_DEBUG | ||
| 801 | PSI_MUTEX_KEY(rw_lock_debug_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 802 | #endif /* UNIV_DEBUG */ | ||
| 803 | PSI_MUTEX_KEY(rw_lock_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 804 | PSI_MUTEX_KEY(rw_lock_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 805 | PSI_MUTEX_KEY(srv_innodb_monitor_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 806 | PSI_MUTEX_KEY(srv_misc_tmpfile_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 807 | PSI_MUTEX_KEY(srv_monitor_file_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 808 | #ifdef UNIV_DEBUG | ||
| 809 | PSI_MUTEX_KEY(sync_thread_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 810 | #endif /* UNIV_DEBUG */ | ||
| 811 | PSI_MUTEX_KEY(trx_undo_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 812 | PSI_MUTEX_KEY(trx_pool_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 813 | PSI_MUTEX_KEY(trx_pool_manager_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 814 | PSI_MUTEX_KEY(temp_pool_manager_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 815 | PSI_MUTEX_KEY(srv_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 816 | PSI_MUTEX_KEY(lock_sys_page_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 817 | PSI_MUTEX_KEY(lock_sys_table_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 818 | PSI_MUTEX_KEY(lock_wait_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 819 | PSI_MUTEX_KEY(trx_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 820 | PSI_MUTEX_KEY(srv_threads_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 821 | #ifndef PFS_SKIP_EVENT_MUTEX | ||
| 822 | PSI_MUTEX_KEY(event_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 823 | PSI_MUTEX_KEY(event_manager_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 824 | #endif /* PFS_SKIP_EVENT_MUTEX */ | ||
| 825 | PSI_MUTEX_KEY(rtr_active_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 826 | PSI_MUTEX_KEY(rtr_match_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 827 | PSI_MUTEX_KEY(rtr_path_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 828 | PSI_MUTEX_KEY(rtr_ssn_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 829 | PSI_MUTEX_KEY(trx_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 830 | PSI_MUTEX_KEY(trx_sys_shard_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 831 | PSI_MUTEX_KEY(trx_sys_serialisation_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 832 | PSI_MUTEX_KEY(zip_pad_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 833 | PSI_MUTEX_KEY(master_key_id_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 834 | PSI_MUTEX_KEY(sync_array_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 835 | PSI_MUTEX_KEY(row_drop_list_mutex, 0, 0, PSI_DOCUMENT_ME)}; | ||
| 836 | #endif /* UNIV_PFS_MUTEX */ | ||
| 837 | |||
| 838 | #ifdef UNIV_PFS_RWLOCK | ||
| 839 | /* all_innodb_rwlocks array contains rwlocks that are | ||
| 840 | performance schema instrumented if "UNIV_PFS_RWLOCK" | ||
| 841 | is defined */ | ||
| 842 | static PSI_rwlock_info all_innodb_rwlocks[] = { | ||
| 843 | PSI_RWLOCK_KEY(btr_search_latch, 0, PSI_DOCUMENT_ME), | ||
| 844 | #ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK | ||
| 845 | PSI_RWLOCK_KEY(buf_block_lock, 0, PSI_DOCUMENT_ME), | ||
| 846 | #endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */ | ||
| 847 | #ifdef UNIV_DEBUG | ||
| 848 | PSI_RWLOCK_KEY(buf_block_debug_latch, 0, PSI_DOCUMENT_ME), | ||
| 849 | #endif /* UNIV_DEBUG */ | ||
| 850 | PSI_RWLOCK_KEY(dict_operation_lock, 0, PSI_DOCUMENT_ME), | ||
| 851 | PSI_RWLOCK_KEY(fil_space_latch, 0, PSI_DOCUMENT_ME), | ||
| 852 | PSI_RWLOCK_KEY(log_sn_lock, 0, PSI_DOCUMENT_ME), | ||
| 853 | PSI_RWLOCK_KEY(undo_spaces_lock, 0, PSI_DOCUMENT_ME), | ||
| 854 | PSI_RWLOCK_KEY(rsegs_lock, 0, PSI_DOCUMENT_ME), | ||
| 855 | PSI_RWLOCK_KEY(lock_sys_global_rw_lock, 0, PSI_DOCUMENT_ME), | ||
| 856 | PSI_RWLOCK_KEY(fts_cache_rw_lock, 0, PSI_DOCUMENT_ME), | ||
| 857 | PSI_RWLOCK_KEY(fts_cache_init_rw_lock, 0, PSI_DOCUMENT_ME), | ||
| 858 | PSI_RWLOCK_KEY(trx_i_s_cache_lock, 0, PSI_DOCUMENT_ME), | ||
| 859 | PSI_RWLOCK_KEY(trx_purge_latch, 0, PSI_DOCUMENT_ME), | ||
| 860 | PSI_RWLOCK_KEY(index_tree_rw_lock, 0, PSI_DOCUMENT_ME), | ||
| 861 | PSI_RWLOCK_KEY(index_online_log, 0, PSI_DOCUMENT_ME), | ||
| 862 | PSI_RWLOCK_KEY(dict_table_stats, 0, PSI_DOCUMENT_ME), | ||
| 863 | PSI_RWLOCK_KEY(hash_table_locks, 0, PSI_DOCUMENT_ME), | ||
| 864 | }; | ||
| 865 | #endif /* UNIV_PFS_RWLOCK */ | ||
| 866 | |||
| 867 | #ifdef UNIV_PFS_THREAD | ||
| 868 | /* all_innodb_threads array contains threads that are | ||
| 869 | performance schema instrumented if "UNIV_PFS_THREAD" | ||
| 870 | is defined */ | ||
| 871 | static PSI_thread_info all_innodb_threads[] = { | ||
| 872 | PSI_THREAD_KEY(log_archiver_thread, "ib_log_arch", PSI_FLAG_SINGLETON, 0, | ||
| 873 | PSI_DOCUMENT_ME), | ||
| 874 | PSI_THREAD_KEY(page_archiver_thread, "ib_page_arch", PSI_FLAG_SINGLETON, 0, | ||
| 875 | PSI_DOCUMENT_ME), | ||
| 876 | PSI_THREAD_KEY(buf_dump_thread, "ib_buf_dump", PSI_FLAG_SINGLETON, 0, | ||
| 877 | PSI_DOCUMENT_ME), | ||
| 878 | PSI_THREAD_KEY(clone_ddl_thread, "ib_clone_ddl", PSI_FLAG_SINGLETON, 0, | ||
| 879 | PSI_DOCUMENT_ME), | ||
| 880 | PSI_THREAD_KEY(clone_gtid_thread, "ib_clone_gtid", PSI_FLAG_SINGLETON, 0, | ||
| 881 | PSI_DOCUMENT_ME), | ||
| 882 | PSI_THREAD_KEY(ddl_thread, "ib_ddl", 0, 0, PSI_DOCUMENT_ME), | ||
| 883 | PSI_THREAD_KEY(dict_stats_thread, "ib_dict_stats", PSI_FLAG_SINGLETON, 0, | ||
| 884 | PSI_DOCUMENT_ME), | ||
| 885 | PSI_THREAD_KEY(io_handler_thread, "ib_io_handler", PSI_FLAG_SINGLETON, 0, | ||
| 886 | PSI_DOCUMENT_ME), | ||
| 887 | PSI_THREAD_KEY(io_ibuf_thread, "ib_io_ibuf", PSI_FLAG_SINGLETON, 0, | ||
| 888 | PSI_DOCUMENT_ME), | ||
| 889 | PSI_THREAD_KEY(io_log_thread, "ib_io_log", PSI_FLAG_SINGLETON, 0, | ||
| 890 | PSI_DOCUMENT_ME), | ||
| 891 | PSI_THREAD_KEY(io_read_thread, "ib_io_rd", 0, 0, PSI_DOCUMENT_ME), | ||
| 892 | PSI_THREAD_KEY(io_write_thread, "ib_io_wr", 0, 0, PSI_DOCUMENT_ME), | ||
| 893 | PSI_THREAD_KEY(buf_resize_thread, "ib_buf_resize", PSI_FLAG_SINGLETON, 0, | ||
| 894 | PSI_DOCUMENT_ME), | ||
| 895 | PSI_THREAD_KEY(log_files_governor_thread, "ib_log_files_g", | ||
| 896 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 897 | PSI_THREAD_KEY(log_writer_thread, "ib_log_writer", PSI_FLAG_SINGLETON, 0, | ||
| 898 | PSI_DOCUMENT_ME), | ||
| 899 | PSI_THREAD_KEY(log_checkpointer_thread, "ib_log_checkpt", | ||
| 900 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 901 | PSI_THREAD_KEY(log_flusher_thread, "ib_log_flush", PSI_FLAG_SINGLETON, 0, | ||
| 902 | PSI_DOCUMENT_ME), | ||
| 903 | PSI_THREAD_KEY(log_write_notifier_thread, "ib_log_wr_notif", | ||
| 904 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 905 | PSI_THREAD_KEY(log_flush_notifier_thread, "ib_log_fl_notif", | ||
| 906 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 907 | PSI_THREAD_KEY(buf_lru_manager_thread, "ib_buf_lru", 0, 0, | ||
| 908 | PSI_DOCUMENT_ME), | ||
| 909 | PSI_THREAD_KEY(recv_writer_thread, "ib_recv_write", PSI_FLAG_SINGLETON, 0, | ||
| 910 | PSI_DOCUMENT_ME), | ||
| 911 | PSI_THREAD_KEY(srv_error_monitor_thread, "ib_srv_err", | ||
| 912 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 913 | PSI_THREAD_KEY(srv_lock_timeout_thread, "ib_srv_lock_to", | ||
| 914 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 915 | PSI_THREAD_KEY(srv_master_thread, "ib_src_main", PSI_FLAG_SINGLETON, 0, | ||
| 916 | PSI_DOCUMENT_ME), | ||
| 917 | PSI_THREAD_KEY(srv_monitor_thread, "ib_srv_mon", PSI_FLAG_SINGLETON, 0, | ||
| 918 | PSI_DOCUMENT_ME), | ||
| 919 | PSI_THREAD_KEY(srv_purge_thread, "ib_srv_purge", PSI_FLAG_SINGLETON, 0, | ||
| 920 | PSI_DOCUMENT_ME), | ||
| 921 | PSI_THREAD_KEY(srv_worker_thread, "ib_srv_wkr", 0, 0, PSI_DOCUMENT_ME), | ||
| 922 | PSI_THREAD_KEY(trx_recovery_rollback_thread, "ib_tx_recov", 0, 0, | ||
| 923 | PSI_DOCUMENT_ME), | ||
| 924 | PSI_THREAD_KEY(page_flush_thread, "ib_pg_flush", 0, 0, PSI_DOCUMENT_ME), | ||
| 925 | PSI_THREAD_KEY(page_flush_coordinator_thread, "ib_pg_flush_co", | ||
| 926 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 927 | PSI_THREAD_KEY(fts_optimize_thread, "ib_fts_opt", PSI_FLAG_SINGLETON, 0, | ||
| 928 | PSI_DOCUMENT_ME), | ||
| 929 | PSI_THREAD_KEY(fts_parallel_merge_thread, "ib_fts_merge", 0, 0, | ||
| 930 | PSI_DOCUMENT_ME), | ||
| 931 | PSI_THREAD_KEY(fts_parallel_tokenization_thread, "ib_fts_token", 0, 0, | ||
| 932 | PSI_DOCUMENT_ME), | ||
| 933 | PSI_THREAD_KEY(srv_ts_alter_encrypt_thread, "ib_ts_encrypt", | ||
| 934 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 935 | PSI_THREAD_KEY(parallel_read_thread, "ib_par_rd", 0, 0, PSI_DOCUMENT_ME), | ||
| 936 | PSI_THREAD_KEY(parallel_rseg_init_thread, "ib_par_rseg", 0, 0, | ||
| 937 | PSI_DOCUMENT_ME), | ||
| 938 | PSI_THREAD_KEY(meb::redo_log_archive_consumer_thread, "ib_meb_rl", | ||
| 939 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME)}; | ||
| 940 | #endif /* UNIV_PFS_THREAD */ | ||
| 941 | |||
| 942 | #ifdef UNIV_PFS_IO | ||
| 943 | /* all_innodb_files array contains the type of files that are | ||
| 944 | performance schema instrumented if "UNIV_PFS_IO" is defined */ | ||
| 945 | static PSI_file_info all_innodb_files[] = { | ||
| 946 | PSI_KEY(innodb_dblwr_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 947 | PSI_KEY(innodb_tablespace_open_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 948 | PSI_KEY(innodb_data_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 949 | PSI_KEY(innodb_log_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 950 | PSI_KEY(innodb_bmp_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 951 | PSI_KEY(innodb_temp_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 952 | PSI_KEY(innodb_arch_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 953 | PSI_KEY(innodb_clone_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 954 | PSI_KEY(meb::redo_log_archive_file, 0, 0, PSI_DOCUMENT_ME)}; | ||
| 955 | #endif /* UNIV_PFS_IO */ | ||
| 956 | #endif /* HAVE_PSI_INTERFACE */ | ||
| 957 | |||
| 958 | 13 | static int default_encryption_key_id_validate( | |
| 959 | /*=================================*/ | ||
| 960 | THD *thd, /*!< in: thread handle */ | ||
| 961 | SYS_VAR *var, /*!< in: pointer to system | ||
| 962 | variable */ | ||
| 963 | void *save, /*!< out: immediate result | ||
| 964 | for update function */ | ||
| 965 | st_mysql_value *value) /*!< in: incoming string */ { | ||
| 966 | long long intbuf; | ||
| 967 | |||
| 968 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | DBUG_ENTER("default_encryption_key_id_validate"); |
| 969 | |||
| 970 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
13 | if (value->val_int(value, &intbuf)) { |
| 971 | /* The value is NULL. That is invalid. */ | ||
| 972 | ✗ | DBUG_RETURN(1); | |
| 973 | } | ||
| 974 | |||
| 975 | 13 | bool is_val_fixed = false; | |
| 976 | 13 | auto key_id = intbuf; | |
| 977 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
|
13 | if (intbuf < 0) { |
| 978 | 3 | key_id = 0; | |
| 979 | 3 | is_val_fixed = true; | |
| 980 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
|
10 | } else if (intbuf >= UINT_MAX32) { |
| 981 | 3 | key_id = UINT_MAX32 - 1; | |
| 982 | 3 | is_val_fixed = true; | |
| 983 | } | ||
| 984 | |||
| 985 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
13 | if (throw_bounds_warning(thd, "innodb_encryption_key_id", is_val_fixed, |
| 986 | intbuf)) { | ||
| 987 | ✗ | DBUG_RETURN(1); | |
| 988 | } | ||
| 989 | |||
| 990 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
13 | if (!Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist( |
| 991 | static_cast<uint>(key_id), server_uuid)) { | ||
| 992 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, | |
| 993 | "InnoDB: cannot enable encryption, " | ||
| 994 | "keyring plugin is not available"); | ||
| 995 | ✗ | DBUG_RETURN(1); | |
| 996 | } | ||
| 997 | |||
| 998 | 13 | *reinterpret_cast<ulong *>(save) = static_cast<ulong>(key_id); | |
| 999 | |||
| 1000 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | DBUG_RETURN(0); |
| 1001 | } | ||
| 1002 | |||
| 1003 | 13 | static void default_encryption_key_id_update( | |
| 1004 | THD *thd, // in: thread handle <] | ||
| 1005 | SYS_VAR *var, // in: pointer to | ||
| 1006 | // system variable */ | ||
| 1007 | void *var_ptr, // where the | ||
| 1008 | // formal string goes */ | ||
| 1009 | const void *save) { // in: immediate result | ||
| 1010 | // from check function | ||
| 1011 | 13 | *static_cast<ulong *>(var_ptr) = *static_cast<const ulong *>(save); | |
| 1012 | 13 | } | |
| 1013 | |||
| 1014 | static MYSQL_THDVAR_UINT(default_encryption_key_id, PLUGIN_VAR_RQCMDARG, | ||
| 1015 | "Default encryption key id used for table encryption.", | ||
| 1016 | default_encryption_key_id_validate, | ||
| 1017 | default_encryption_key_id_update, | ||
| 1018 | FIL_DEFAULT_ENCRYPTION_KEY, 0, UINT_MAX32 - 1, 0); | ||
| 1019 | |||
| 1020 | 418 | uint get_global_default_encryption_key_id_value() { | |
| 1021 | 418 | return THDVAR(NULL, default_encryption_key_id); | |
| 1022 | } | ||
| 1023 | |||
| 1024 | static MYSQL_THDVAR_UINT(records_in_range, PLUGIN_VAR_RQCMDARG, | ||
| 1025 | "Used to override the result of records_in_range(). " | ||
| 1026 | "Set to a positive number to override", | ||
| 1027 | NULL, NULL, 0, | ||
| 1028 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1029 | |||
| 1030 | static MYSQL_THDVAR_UINT(force_index_records_in_range, PLUGIN_VAR_RQCMDARG, | ||
| 1031 | "Used to override the result of records_in_range() " | ||
| 1032 | "when FORCE INDEX is used.", | ||
| 1033 | NULL, NULL, 0, | ||
| 1034 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1035 | |||
| 1036 | 39 | uint innodb_force_index_records_in_range(THD *thd) { | |
| 1037 | 39 | return THDVAR(thd, force_index_records_in_range); | |
| 1038 | } | ||
| 1039 | |||
| 1040 | 23614 | uint innodb_records_in_range(THD *thd) { return THDVAR(thd, records_in_range); } | |
| 1041 | |||
| 1042 | /** Plugin update function to handle validation and then switch the | ||
| 1043 | innodb_doublewrite mode | ||
| 1044 | @param[in] thd thread handle | ||
| 1045 | @param[in] var pointer to system variable | ||
| 1046 | @param[in] var_ptr where the formal string goes | ||
| 1047 | @param[in] save immediate result from check function */ | ||
| 1048 | 92 | static void doublewrite_update(THD *thd [[maybe_unused]], | |
| 1049 | SYS_VAR *var [[maybe_unused]], void *var_ptr, | ||
| 1050 | const void *save) { | ||
| 1051 | 92 | ulong new_value = *static_cast<const ulong *>(save); | |
| 1052 | |||
| 1053 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 75 times.
|
92 | if (dblwr::Mode::is_enabled_to_disabled(new_value)) { |
| 1054 | char msg[FN_REFLEN]; | ||
| 1055 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | snprintf(msg, sizeof(msg), |
| 1056 | "InnoDB: cannot change doublewrite mode to %s if" | ||
| 1057 | " doublewrite is enabled. Please shutdown and" | ||
| 1058 | " change value to %s", | ||
| 1059 | dblwr::Mode::to_string(new_value), | ||
| 1060 | dblwr::Mode::to_string(new_value)); | ||
| 1061 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | my_error(ER_WRONG_ARGUMENTS, MYF(0), msg); |
| 1062 | 17 | return; | |
| 1063 | } | ||
| 1064 | |||
| 1065 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 59 times.
|
75 | if (dblwr::Mode::is_disabled_to_enabled(new_value)) { |
| 1066 | char msg[FN_REFLEN]; | ||
| 1067 |
2/4✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | snprintf(msg, sizeof(msg), |
| 1068 | "InnoDB: cannot change doublewrite mode to %s if" | ||
| 1069 | " doublewrite is disabled. Please shutdown and" | ||
| 1070 | " change value to %s", | ||
| 1071 | dblwr::Mode::to_string(new_value), | ||
| 1072 | dblwr::Mode::to_string(new_value)); | ||
| 1073 | |||
| 1074 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | my_error(ER_WRONG_ARGUMENTS, MYF(0), msg); |
| 1075 | |||
| 1076 | 16 | return; | |
| 1077 | } | ||
| 1078 | |||
| 1079 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 35 times.
|
59 | if (dblwr::Mode::is_same(new_value)) { |
| 1080 | 24 | return; | |
| 1081 | } | ||
| 1082 | |||
| 1083 | /* Handle DETECT_AND_RECOVER to DETECT_ONLY | ||
| 1084 | 1. Check if DETECT_ONLY setup is already initalized. If not, intialize | ||
| 1085 | DETECT_ONLY files and structures. | ||
| 1086 | 2. Flush the partially filled dblwr buffers. */ | ||
| 1087 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 18 times.
|
35 | if (dblwr::Mode::is_reduced_low(new_value)) { |
| 1088 | 17 | dberr_t err = dblwr::enable_reduced(); | |
| 1089 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (err != DB_SUCCESS) { |
| 1090 | char msg[FN_REFLEN]; | ||
| 1091 | ✗ | snprintf(msg, sizeof(msg), | |
| 1092 | "InnoDB: cannot change doublewrite mode to %s." | ||
| 1093 | " Please check if doublewrite directory is writable" | ||
| 1094 | " Error code: %d", | ||
| 1095 | dblwr::Mode::to_string(new_value), err); | ||
| 1096 | ✗ | my_error(ER_WRONG_ARGUMENTS, MYF(0), msg); | |
| 1097 | ✗ | return; | |
| 1098 | } | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | /* Handle DETECT_ONLY to DETECT_AND_RECOVER. | ||
| 1102 | 1. Flush partially filled reduced dblwr buffers */ | ||
| 1103 | 35 | dblwr::force_flush_all(); | |
| 1104 | |||
| 1105 | 35 | *static_cast<ulong *>(var_ptr) = *static_cast<const ulong *>(save); | |
| 1106 | } | ||
| 1107 | |||
| 1108 | /** Set up InnoDB API callback function array */ | ||
| 1109 | /* | ||
| 1110 | Generates array elements which look like: | ||
| 1111 | (ib_cb_t)ib_cursor_open_table, | ||
| 1112 | for each api function. | ||
| 1113 | */ | ||
| 1114 | #define INNODB_API_CB_ARRAY_ELEMENT_TRANSFORM(stem) (ib_cb_t) ib_##stem, | ||
| 1115 | |||
| 1116 | static ib_cb_t innodb_api_cb[] = { | ||
| 1117 | FOR_EACH_API_METHOD_NAME_STEM(INNODB_API_CB_ARRAY_ELEMENT_TRANSFORM)}; | ||
| 1118 | |||
| 1119 | static int innodb_check_session_admin(THD *thd, SYS_VAR *self, void *save, | ||
| 1120 | struct st_mysql_value *value); | ||
| 1121 | |||
| 1122 | /**Check whether valid argument given to innobase_*_stopword_table. | ||
| 1123 | This function is registered as a callback with MySQL. | ||
| 1124 | @param[in] thd thread handle | ||
| 1125 | @param[in] var pointer to system variable | ||
| 1126 | @param[out] save immediate result for update function | ||
| 1127 | @param[in] value incoming string | ||
| 1128 | @return 0 for valid stopword table */ | ||
| 1129 | static int innodb_stopword_table_validate(THD *thd, SYS_VAR *var, void *save, | ||
| 1130 | struct st_mysql_value *value); | ||
| 1131 | |||
| 1132 | /** Validate passed-in "value" is a valid directory name. | ||
| 1133 | This function is registered as a callback with MySQL. | ||
| 1134 | @param[in,out] thd thread handle | ||
| 1135 | @param[out] save immediate result for update | ||
| 1136 | @param[in] value incoming string | ||
| 1137 | @return 0 for valid name */ | ||
| 1138 | 17 | static int innodb_tmpdir_validate(THD *thd, SYS_VAR *, void *save, | |
| 1139 | struct st_mysql_value *value) { | ||
| 1140 | char *alter_tmp_dir; | ||
| 1141 | char *innodb_tmp_dir; | ||
| 1142 | char buff[OS_FILE_MAX_PATH]; | ||
| 1143 | 17 | int len = sizeof(buff); | |
| 1144 | char tmp_abs_path[FN_REFLEN + 2]; | ||
| 1145 | |||
| 1146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | ut_ad(save != nullptr); |
| 1147 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | ut_ad(value != nullptr); |
| 1148 | |||
| 1149 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
17 | if (check_global_access(thd, FILE_ACL)) { |
| 1150 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 1151 | "InnoDB: FILE Permissions required"); | ||
| 1152 | ✗ | *static_cast<const char **>(save) = nullptr; | |
| 1153 | ✗ | return (1); | |
| 1154 | } | ||
| 1155 | |||
| 1156 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | alter_tmp_dir = (char *)value->val_str(value, buff, &len); |
| 1157 | |||
| 1158 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 8 times.
|
17 | if (!alter_tmp_dir) { |
| 1159 | 9 | *static_cast<const char **>(save) = alter_tmp_dir; | |
| 1160 | 9 | return (0); | |
| 1161 | } | ||
| 1162 | |||
| 1163 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 | if (strlen(alter_tmp_dir) > FN_REFLEN) { |
| 1164 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, |
| 1165 | "Path length should not exceed %d bytes", FN_REFLEN); | ||
| 1166 | 1 | *static_cast<const char **>(save) = nullptr; | |
| 1167 | 1 | return (1); | |
| 1168 | } | ||
| 1169 | |||
| 1170 | 7 | Fil_path::normalize(alter_tmp_dir); | |
| 1171 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_realpath(tmp_abs_path, alter_tmp_dir, 0); |
| 1172 | 7 | size_t tmp_abs_len = strlen(tmp_abs_path); | |
| 1173 | |||
| 1174 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
|
7 | if (my_access(tmp_abs_path, F_OK)) { |
| 1175 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, |
| 1176 | "InnoDB: Path doesn't exist."); | ||
| 1177 | 2 | *static_cast<const char **>(save) = nullptr; | |
| 1178 | 2 | return (1); | |
| 1179 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | } else if (my_access(tmp_abs_path, R_OK | W_OK)) { |
| 1180 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 1181 | "InnoDB: Server doesn't have permission in " | ||
| 1182 | "the given location."); | ||
| 1183 | ✗ | *static_cast<const char **>(save) = nullptr; | |
| 1184 | ✗ | return (1); | |
| 1185 | } | ||
| 1186 | |||
| 1187 | MY_STAT stat_info_dir; | ||
| 1188 | |||
| 1189 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if (my_stat(tmp_abs_path, &stat_info_dir, MYF(0))) { |
| 1190 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if ((stat_info_dir.st_mode & S_IFDIR) != S_IFDIR) { |
| 1191 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 1192 | "Given path is not a directory. "); | ||
| 1193 | ✗ | *static_cast<const char **>(save) = nullptr; | |
| 1194 | ✗ | return (1); | |
| 1195 | } | ||
| 1196 | } | ||
| 1197 | |||
| 1198 |
3/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
|
5 | if (!is_mysql_datadir_path(tmp_abs_path)) { |
| 1199 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, |
| 1200 | "InnoDB: Path location should not be same as " | ||
| 1201 | "mysql data directory location."); | ||
| 1202 | 1 | *static_cast<const char **>(save) = nullptr; | |
| 1203 | 1 | return (1); | |
| 1204 | } | ||
| 1205 | |||
| 1206 | innodb_tmp_dir = | ||
| 1207 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | static_cast<char *>(thd_memdup(thd, tmp_abs_path, tmp_abs_len + 1)); |
| 1208 | 4 | *static_cast<const char **>(save) = innodb_tmp_dir; | |
| 1209 | 4 | return (0); | |
| 1210 | } | ||
| 1211 | |||
| 1212 | /** Empty free list algorithm. | ||
| 1213 | Checks if buffer pool is big enough to enable backoff algorithm. | ||
| 1214 | InnoDB empty free list algorithm backoff requires free pages | ||
| 1215 | from LRU for the best performance. | ||
| 1216 | buf_LRU_buf_pool_running_out cancels query if 1/4 of | ||
| 1217 | buffer pool belongs to LRU or freelist. | ||
| 1218 | At the same time buf_flush_LRU_list_batch | ||
| 1219 | keeps up to BUF_LRU_MIN_LEN in LRU. | ||
| 1220 | In order to avoid deadlock backoff requires buffer pool | ||
| 1221 | to be at least 4*BUF_LRU_MIN_LEN, | ||
| 1222 | but flush peformance is bad because of trashing | ||
| 1223 | and additional BUF_LRU_MIN_LEN pages are requested. | ||
| 1224 | @param[in] algorithm desired algorithm from srv_empty_free_list_t | ||
| 1225 | @param[in] new_buf_pool_sz requested buffer pool size | ||
| 1226 | @return true if it's possible to enable backoff. */ | ||
| 1227 | 9766 | static bool innodb_empty_free_list_algorithm_allowed( | |
| 1228 | srv_empty_free_list_t algorithm, long long new_buf_pool_sz = 0) { | ||
| 1229 |
2/2✓ Branch 0 taken 9737 times.
✓ Branch 1 taken 29 times.
|
9766 | if (!new_buf_pool_sz) new_buf_pool_sz = srv_buf_pool_size; |
| 1230 | |||
| 1231 | 9766 | const long long buf_pool_pages = | |
| 1232 | 9766 | new_buf_pool_sz / srv_page_size / srv_buf_pool_instances; | |
| 1233 | |||
| 1234 |
4/4✓ Branch 0 taken 34 times.
✓ Branch 1 taken 9732 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 5 times.
|
9766 | return (buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1) || |
| 1235 | 9766 | algorithm != SRV_EMPTY_FREE_LIST_BACKOFF); | |
| 1236 | } | ||
| 1237 | |||
| 1238 | /** Gets field offset for a field in a table. | ||
| 1239 | @param[in] table MySQL table object | ||
| 1240 | @param[in] field MySQL field object | ||
| 1241 | @return offset */ | ||
| 1242 | static inline uint get_field_offset(const TABLE *table, const Field *field); | ||
| 1243 | |||
| 1244 | static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG, | ||
| 1245 | "Enable InnoDB locking in LOCK TABLES", | ||
| 1246 | /* check_func */ nullptr, /* update_func */ nullptr, | ||
| 1247 | /* default */ true); | ||
| 1248 | |||
| 1249 | static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG, | ||
| 1250 | "Use strict mode when evaluating create options.", | ||
| 1251 | innodb_check_session_admin, nullptr, true); | ||
| 1252 | |||
| 1253 | static MYSQL_THDVAR_BOOL(ft_enable_stopword, | ||
| 1254 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1255 | "Create FTS index with stopword.", nullptr, nullptr, | ||
| 1256 | /* default */ true); | ||
| 1257 | |||
| 1258 | static MYSQL_THDVAR_ULONG(lock_wait_timeout, | ||
| 1259 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1260 | "Timeout in seconds an InnoDB transaction may wait " | ||
| 1261 | "for a lock before being rolled back. Values above " | ||
| 1262 | "100000000 disable the timeout.", | ||
| 1263 | nullptr, nullptr, 50, 1, 1024 * 1024 * 1024, 0); | ||
| 1264 | |||
| 1265 | static MYSQL_THDVAR_STR( | ||
| 1266 | ft_user_stopword_table, | ||
| 1267 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1268 | "User supplied stopword table name, effective in the session level.", | ||
| 1269 | innodb_stopword_table_validate, nullptr, nullptr); | ||
| 1270 | |||
| 1271 | static MYSQL_THDVAR_STR(tmpdir, | ||
| 1272 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC | | ||
| 1273 | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1274 | "Directory for temporary non-tablespace files.", | ||
| 1275 | innodb_tmpdir_validate, nullptr, nullptr); | ||
| 1276 | |||
| 1277 | static MYSQL_THDVAR_BOOL(ft_ignore_stopwords, PLUGIN_VAR_OPCMDARG, | ||
| 1278 | "Instruct FTS to ignore stopwords.", nullptr, nullptr, | ||
| 1279 | false); | ||
| 1280 | |||
| 1281 | static MYSQL_THDVAR_ULONG(parallel_read_threads, PLUGIN_VAR_RQCMDARG, | ||
| 1282 | "Number of threads to do parallel read.", nullptr, | ||
| 1283 | nullptr, 4, /* Default. */ | ||
| 1284 | 1, /* Minimum. */ | ||
| 1285 | Parallel_reader::MAX_THREADS, /* Maxumum. */ | ||
| 1286 | 0); | ||
| 1287 | |||
| 1288 | static MYSQL_THDVAR_ULONG(ddl_buffer_size, PLUGIN_VAR_RQCMDARG, | ||
| 1289 | "Maximum size of memory to use (in bytes) for DDL.", | ||
| 1290 | nullptr, nullptr, 1048576, /* Default. */ | ||
| 1291 | 65536, /* Minimum. */ | ||
| 1292 | 4294967295, 0); /* Maximum. */ | ||
| 1293 | |||
| 1294 | static MYSQL_THDVAR_ULONG(ddl_threads, PLUGIN_VAR_RQCMDARG, | ||
| 1295 | "Maximum number of threads to use for DDL.", nullptr, | ||
| 1296 | nullptr, 4, /* Default. */ | ||
| 1297 | 1, /* Minimum. */ | ||
| 1298 | 64, 0); /* Maximum. */ | ||
| 1299 | |||
| 1300 | static SHOW_VAR innodb_status_variables[] = { | ||
| 1301 | {"background_log_sync", (char *)&export_vars.innodb_background_log_sync, | ||
| 1302 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1303 | {"buffer_pool_dump_status", | ||
| 1304 | (char *)&export_vars.innodb_buffer_pool_dump_status, SHOW_CHAR, | ||
| 1305 | SHOW_SCOPE_GLOBAL}, | ||
| 1306 | {"buffer_pool_load_status", | ||
| 1307 | (char *)&export_vars.innodb_buffer_pool_load_status, SHOW_CHAR, | ||
| 1308 | SHOW_SCOPE_GLOBAL}, | ||
| 1309 | {"buffer_pool_resize_status", | ||
| 1310 | (char *)&export_vars.innodb_buffer_pool_resize_status, SHOW_CHAR, | ||
| 1311 | SHOW_SCOPE_GLOBAL}, | ||
| 1312 | {"buffer_pool_pages_data", | ||
| 1313 | (char *)&export_vars.innodb_buffer_pool_pages_data, SHOW_LONG, | ||
| 1314 | SHOW_SCOPE_GLOBAL}, | ||
| 1315 | {"buffer_pool_bytes_data", | ||
| 1316 | (char *)&export_vars.innodb_buffer_pool_bytes_data, SHOW_LONG, | ||
| 1317 | SHOW_SCOPE_GLOBAL}, | ||
| 1318 | {"buffer_pool_pages_dirty", | ||
| 1319 | (char *)&export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG, | ||
| 1320 | SHOW_SCOPE_GLOBAL}, | ||
| 1321 | {"buffer_pool_bytes_dirty", | ||
| 1322 | (char *)&export_vars.innodb_buffer_pool_bytes_dirty, SHOW_LONG, | ||
| 1323 | SHOW_SCOPE_GLOBAL}, | ||
| 1324 | {"buffer_pool_pages_flushed", | ||
| 1325 | (char *)&export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG, | ||
| 1326 | SHOW_SCOPE_GLOBAL}, | ||
| 1327 | {"buffer_pool_pages_free", | ||
| 1328 | (char *)&export_vars.innodb_buffer_pool_pages_free, SHOW_LONG, | ||
| 1329 | SHOW_SCOPE_GLOBAL}, | ||
| 1330 | #ifdef UNIV_DEBUG | ||
| 1331 | {"buffer_pool_pages_latched", | ||
| 1332 | (char *)&export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG, | ||
| 1333 | SHOW_SCOPE_GLOBAL}, | ||
| 1334 | #endif /* UNIV_DEBUG */ | ||
| 1335 | {"buffer_pool_pages_LRU_flushed", | ||
| 1336 | (char *)&export_vars.innodb_buffer_pool_pages_LRU_flushed, SHOW_LONG, | ||
| 1337 | SHOW_SCOPE_GLOBAL}, | ||
| 1338 | {"buffer_pool_pages_made_not_young", | ||
| 1339 | (char *)&export_vars.innodb_buffer_pool_pages_made_not_young, SHOW_LONG, | ||
| 1340 | SHOW_SCOPE_GLOBAL}, | ||
| 1341 | {"buffer_pool_pages_made_young", | ||
| 1342 | (char *)&export_vars.innodb_buffer_pool_pages_made_young, SHOW_LONG, | ||
| 1343 | SHOW_SCOPE_GLOBAL}, | ||
| 1344 | {"buffer_pool_pages_misc", | ||
| 1345 | (char *)&export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG, | ||
| 1346 | SHOW_SCOPE_GLOBAL}, | ||
| 1347 | {"buffer_pool_pages_old", (char *)&export_vars.innodb_buffer_pool_pages_old, | ||
| 1348 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1349 | {"buffer_pool_pages_total", | ||
| 1350 | (char *)&export_vars.innodb_buffer_pool_pages_total, SHOW_LONG, | ||
| 1351 | SHOW_SCOPE_GLOBAL}, | ||
| 1352 | {"buffer_pool_read_ahead_rnd", | ||
| 1353 | (char *)&export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG, | ||
| 1354 | SHOW_SCOPE_GLOBAL}, | ||
| 1355 | {"buffer_pool_read_ahead", | ||
| 1356 | (char *)&export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG, | ||
| 1357 | SHOW_SCOPE_GLOBAL}, | ||
| 1358 | {"buffer_pool_read_ahead_evicted", | ||
| 1359 | (char *)&export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG, | ||
| 1360 | SHOW_SCOPE_GLOBAL}, | ||
| 1361 | {"buffer_pool_read_requests", | ||
| 1362 | (char *)&export_vars.innodb_buffer_pool_read_requests, SHOW_LONG, | ||
| 1363 | SHOW_SCOPE_GLOBAL}, | ||
| 1364 | {"buffer_pool_reads", (char *)&export_vars.innodb_buffer_pool_reads, | ||
| 1365 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1366 | {"buffer_pool_wait_free", (char *)&export_vars.innodb_buffer_pool_wait_free, | ||
| 1367 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1368 | {"buffer_pool_write_requests", | ||
| 1369 | (char *)&export_vars.innodb_buffer_pool_write_requests, SHOW_LONG, | ||
| 1370 | SHOW_SCOPE_GLOBAL}, | ||
| 1371 | {"checkpoint_age", (char *)&export_vars.innodb_checkpoint_age, SHOW_LONG, | ||
| 1372 | SHOW_SCOPE_GLOBAL}, | ||
| 1373 | {"checkpoint_max_age", (char *)&export_vars.innodb_checkpoint_max_age, | ||
| 1374 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1375 | {"data_fsyncs", (char *)&export_vars.innodb_data_fsyncs, SHOW_LONG, | ||
| 1376 | SHOW_SCOPE_GLOBAL}, | ||
| 1377 | {"data_pending_fsyncs", (char *)&export_vars.innodb_data_pending_fsyncs, | ||
| 1378 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1379 | {"data_pending_reads", (char *)&export_vars.innodb_data_pending_reads, | ||
| 1380 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1381 | {"data_pending_writes", (char *)&export_vars.innodb_data_pending_writes, | ||
| 1382 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1383 | {"data_read", (char *)&export_vars.innodb_data_read, SHOW_LONG, | ||
| 1384 | SHOW_SCOPE_GLOBAL}, | ||
| 1385 | {"data_reads", (char *)&export_vars.innodb_data_reads, SHOW_LONG, | ||
| 1386 | SHOW_SCOPE_GLOBAL}, | ||
| 1387 | {"data_writes", (char *)&export_vars.innodb_data_writes, SHOW_LONG, | ||
| 1388 | SHOW_SCOPE_GLOBAL}, | ||
| 1389 | {"data_written", (char *)&export_vars.innodb_data_written, SHOW_LONG, | ||
| 1390 | SHOW_SCOPE_GLOBAL}, | ||
| 1391 | {"dblwr_pages_written", (char *)&export_vars.innodb_dblwr_pages_written, | ||
| 1392 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1393 | {"dblwr_writes", (char *)&export_vars.innodb_dblwr_writes, SHOW_LONG, | ||
| 1394 | SHOW_SCOPE_GLOBAL}, | ||
| 1395 | {"ibuf_free_list", (char *)&export_vars.innodb_ibuf_free_list, SHOW_LONG, | ||
| 1396 | SHOW_SCOPE_GLOBAL}, | ||
| 1397 | {"ibuf_segment_size", (char *)&export_vars.innodb_ibuf_segment_size, | ||
| 1398 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1399 | {"redo_log_read_only", (char *)&export_vars.innodb_redo_log_read_only, | ||
| 1400 | SHOW_BOOL, SHOW_SCOPE_GLOBAL}, | ||
| 1401 | {"redo_log_uuid", (char *)&export_vars.innodb_redo_log_uuid, SHOW_LONGLONG, | ||
| 1402 | SHOW_SCOPE_GLOBAL}, | ||
| 1403 | {"redo_log_checkpoint_lsn", | ||
| 1404 | (char *)&export_vars.innodb_redo_log_checkpoint_lsn, SHOW_LONGLONG, | ||
| 1405 | SHOW_SCOPE_GLOBAL}, | ||
| 1406 | {"redo_log_current_lsn", (char *)&export_vars.innodb_redo_log_current_lsn, | ||
| 1407 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1408 | {"redo_log_flushed_to_disk_lsn", | ||
| 1409 | (char *)&export_vars.innodb_redo_log_flushed_to_disk_lsn, SHOW_LONGLONG, | ||
| 1410 | SHOW_SCOPE_GLOBAL}, | ||
| 1411 | {"redo_log_logical_size", (char *)&export_vars.innodb_redo_log_logical_size, | ||
| 1412 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1413 | {"redo_log_physical_size", | ||
| 1414 | (char *)&export_vars.innodb_redo_log_physical_size, SHOW_LONGLONG, | ||
| 1415 | SHOW_SCOPE_GLOBAL}, | ||
| 1416 | {"redo_log_capacity_resized", | ||
| 1417 | (char *)&export_vars.innodb_redo_log_capacity_resized, SHOW_LONGLONG, | ||
| 1418 | SHOW_SCOPE_GLOBAL}, | ||
| 1419 | {"redo_log_resize_status", | ||
| 1420 | (char *)&export_vars.innodb_redo_log_resize_status, SHOW_CHAR, | ||
| 1421 | SHOW_SCOPE_GLOBAL}, | ||
| 1422 | {"log_waits", (char *)&export_vars.innodb_log_waits, SHOW_LONG, | ||
| 1423 | SHOW_SCOPE_GLOBAL}, | ||
| 1424 | {"log_write_requests", (char *)&export_vars.innodb_log_write_requests, | ||
| 1425 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1426 | {"log_writes", (char *)&export_vars.innodb_log_writes, SHOW_LONG, | ||
| 1427 | SHOW_SCOPE_GLOBAL}, | ||
| 1428 | {"lsn_current", (char *)&export_vars.innodb_lsn_current, SHOW_LONGLONG, | ||
| 1429 | SHOW_SCOPE_GLOBAL}, | ||
| 1430 | {"lsn_flushed", (char *)&export_vars.innodb_lsn_flushed, SHOW_LONGLONG, | ||
| 1431 | SHOW_SCOPE_GLOBAL}, | ||
| 1432 | {"lsn_last_checkpoint", (char *)&export_vars.innodb_lsn_last_checkpoint, | ||
| 1433 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1434 | {"master_thread_active_loops", | ||
| 1435 | (char *)&export_vars.innodb_master_thread_active_loops, SHOW_LONG, | ||
| 1436 | SHOW_SCOPE_GLOBAL}, | ||
| 1437 | {"master_thread_idle_loops", | ||
| 1438 | (char *)&export_vars.innodb_master_thread_idle_loops, SHOW_LONG, | ||
| 1439 | SHOW_SCOPE_GLOBAL}, | ||
| 1440 | {"max_trx_id", (char *)&export_vars.innodb_max_trx_id, SHOW_LONGLONG, | ||
| 1441 | SHOW_SCOPE_GLOBAL}, | ||
| 1442 | {"oldest_view_low_limit_trx_id", | ||
| 1443 | (char *)&export_vars.innodb_oldest_view_low_limit_trx_id, SHOW_LONGLONG, | ||
| 1444 | SHOW_SCOPE_GLOBAL}, | ||
| 1445 | {"os_log_fsyncs", (char *)&export_vars.innodb_os_log_fsyncs, SHOW_LONG, | ||
| 1446 | SHOW_SCOPE_GLOBAL}, | ||
| 1447 | {"os_log_pending_fsyncs", (char *)&export_vars.innodb_os_log_pending_fsyncs, | ||
| 1448 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1449 | {"os_log_pending_writes", (char *)&export_vars.innodb_os_log_pending_writes, | ||
| 1450 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1451 | {"os_log_written", (char *)&export_vars.innodb_os_log_written, | ||
| 1452 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1453 | {"page_size", (char *)&export_vars.innodb_page_size, SHOW_LONG, | ||
| 1454 | SHOW_SCOPE_GLOBAL}, | ||
| 1455 | {"pages_created", (char *)&export_vars.innodb_pages_created, SHOW_LONG, | ||
| 1456 | SHOW_SCOPE_GLOBAL}, | ||
| 1457 | {"pages_read", (char *)&export_vars.innodb_pages_read, SHOW_LONG, | ||
| 1458 | SHOW_SCOPE_GLOBAL}, | ||
| 1459 | {"pages0_read", (char *)&export_vars.innodb_page0_read, SHOW_LONG, | ||
| 1460 | SHOW_SCOPE_GLOBAL}, | ||
| 1461 | {"pages_written", (char *)&export_vars.innodb_pages_written, SHOW_LONG, | ||
| 1462 | SHOW_SCOPE_GLOBAL}, | ||
| 1463 | {"purge_trx_id", (char *)&export_vars.innodb_purge_trx_id, SHOW_LONGLONG, | ||
| 1464 | SHOW_SCOPE_GLOBAL}, | ||
| 1465 | {"purge_undo_no", (char *)&export_vars.innodb_purge_undo_no, SHOW_LONGLONG, | ||
| 1466 | SHOW_SCOPE_GLOBAL}, | ||
| 1467 | {"redo_log_enabled", (char *)&export_vars.innodb_redo_log_enabled, | ||
| 1468 | SHOW_BOOL, SHOW_SCOPE_GLOBAL}, | ||
| 1469 | {"row_lock_current_waits", | ||
| 1470 | (char *)&export_vars.innodb_row_lock_current_waits, SHOW_LONG, | ||
| 1471 | SHOW_SCOPE_GLOBAL}, | ||
| 1472 | {"row_lock_time", (char *)&export_vars.innodb_row_lock_time, SHOW_LONGLONG, | ||
| 1473 | SHOW_SCOPE_GLOBAL}, | ||
| 1474 | {"row_lock_time_avg", (char *)&export_vars.innodb_row_lock_time_avg, | ||
| 1475 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1476 | {"row_lock_time_max", (char *)&export_vars.innodb_row_lock_time_max, | ||
| 1477 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1478 | {"row_lock_waits", (char *)&export_vars.innodb_row_lock_waits, SHOW_LONG, | ||
| 1479 | SHOW_SCOPE_GLOBAL}, | ||
| 1480 | {"rows_deleted", (char *)&export_vars.innodb_rows_deleted, SHOW_LONG, | ||
| 1481 | SHOW_SCOPE_GLOBAL}, | ||
| 1482 | {"rows_inserted", (char *)&export_vars.innodb_rows_inserted, SHOW_LONG, | ||
| 1483 | SHOW_SCOPE_GLOBAL}, | ||
| 1484 | {"rows_read", (char *)&export_vars.innodb_rows_read, SHOW_LONG, | ||
| 1485 | SHOW_SCOPE_GLOBAL}, | ||
| 1486 | {"rows_updated", (char *)&export_vars.innodb_rows_updated, SHOW_LONG, | ||
| 1487 | SHOW_SCOPE_GLOBAL}, | ||
| 1488 | {"system_rows_deleted", (char *)&export_vars.innodb_system_rows_deleted, | ||
| 1489 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1490 | {"system_rows_inserted", (char *)&export_vars.innodb_system_rows_inserted, | ||
| 1491 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1492 | {"system_rows_read", (char *)&export_vars.innodb_system_rows_read, | ||
| 1493 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1494 | {"system_rows_updated", (char *)&export_vars.innodb_system_rows_updated, | ||
| 1495 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1496 | {"sampled_pages_read", (char *)&export_vars.innodb_sampled_pages_read, | ||
| 1497 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1498 | {"sampled_pages_skipped", (char *)&export_vars.innodb_sampled_pages_skipped, | ||
| 1499 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1500 | {"num_open_files", (char *)&export_vars.innodb_num_open_files, SHOW_LONG, | ||
| 1501 | SHOW_SCOPE_GLOBAL}, | ||
| 1502 | {"truncated_status_writes", | ||
| 1503 | (char *)&export_vars.innodb_truncated_status_writes, SHOW_LONG, | ||
| 1504 | SHOW_SCOPE_GLOBAL}, | ||
| 1505 | {"undo_tablespaces_total", | ||
| 1506 | (char *)&export_vars.innodb_undo_tablespaces_total, SHOW_LONG, | ||
| 1507 | SHOW_SCOPE_GLOBAL}, | ||
| 1508 | {"undo_tablespaces_implicit", | ||
| 1509 | (char *)&export_vars.innodb_undo_tablespaces_implicit, SHOW_LONG, | ||
| 1510 | SHOW_SCOPE_GLOBAL}, | ||
| 1511 | {"undo_tablespaces_explicit", | ||
| 1512 | (char *)&export_vars.innodb_undo_tablespaces_explicit, SHOW_LONG, | ||
| 1513 | SHOW_SCOPE_GLOBAL}, | ||
| 1514 | {"undo_tablespaces_active", | ||
| 1515 | (char *)&export_vars.innodb_undo_tablespaces_active, SHOW_LONG, | ||
| 1516 | SHOW_SCOPE_GLOBAL}, | ||
| 1517 | #ifdef UNIV_DEBUG | ||
| 1518 | {"purge_trx_id_age", (char *)&export_vars.innodb_purge_trx_id_age, | ||
| 1519 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1520 | {"purge_view_trx_id_age", (char *)&export_vars.innodb_purge_view_trx_id_age, | ||
| 1521 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1522 | {"ahi_drop_lookups", (char *)&export_vars.innodb_ahi_drop_lookups, | ||
| 1523 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1524 | #endif /* UNIV_DEBUG */ | ||
| 1525 | {"secondary_index_triggered_cluster_reads", | ||
| 1526 | (char *)&export_vars.innodb_sec_rec_cluster_reads, SHOW_LONG, | ||
| 1527 | SHOW_SCOPE_GLOBAL}, | ||
| 1528 | {"secondary_index_triggered_cluster_reads_avoided", | ||
| 1529 | (char *)&export_vars.innodb_sec_rec_cluster_reads_avoided, SHOW_LONG, | ||
| 1530 | SHOW_SCOPE_GLOBAL}, | ||
| 1531 | {"buffered_aio_submitted", | ||
| 1532 | (char *)&export_vars.innodb_buffered_aio_submitted, SHOW_LONG, | ||
| 1533 | SHOW_SCOPE_GLOBAL}, | ||
| 1534 | |||
| 1535 | {"scan_pages_contiguous", | ||
| 1536 | (char *)&export_vars.innodb_fragmentation_stats.scan_pages_contiguous, | ||
| 1537 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1538 | {"scan_pages_disjointed", | ||
| 1539 | (char *)&export_vars.innodb_fragmentation_stats.scan_pages_disjointed, | ||
| 1540 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1541 | {"scan_pages_total_seek_distance", | ||
| 1542 | (char *)&export_vars.innodb_fragmentation_stats | ||
| 1543 | .scan_pages_total_seek_distance, | ||
| 1544 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1545 | {"scan_data_size", | ||
| 1546 | (char *)&export_vars.innodb_fragmentation_stats.scan_data_size, SHOW_LONG, | ||
| 1547 | SHOW_SCOPE_GLOBAL}, | ||
| 1548 | {"scan_deleted_recs_size", | ||
| 1549 | (char *)&export_vars.innodb_fragmentation_stats.scan_deleted_recs_size, | ||
| 1550 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1551 | {"encryption_n_merge_blocks_encrypted", | ||
| 1552 | (char *)&export_vars.innodb_n_merge_blocks_encrypted, SHOW_LONGLONG, | ||
| 1553 | SHOW_SCOPE_GLOBAL}, | ||
| 1554 | {"encryption_n_merge_blocks_decrypted", | ||
| 1555 | (char *)&export_vars.innodb_n_merge_blocks_decrypted, SHOW_LONGLONG, | ||
| 1556 | SHOW_SCOPE_GLOBAL}, | ||
| 1557 | {"encryption_n_rowlog_blocks_encrypted", | ||
| 1558 | (char *)&export_vars.innodb_n_rowlog_blocks_encrypted, SHOW_LONGLONG, | ||
| 1559 | SHOW_SCOPE_GLOBAL}, | ||
| 1560 | {"encryption_n_rowlog_blocks_decrypted", | ||
| 1561 | (char *)&export_vars.innodb_n_rowlog_blocks_decrypted, SHOW_LONGLONG, | ||
| 1562 | SHOW_SCOPE_GLOBAL}, | ||
| 1563 | {"encryption_redo_key_version", | ||
| 1564 | (char *)&export_vars.innodb_redo_key_version, SHOW_LONGLONG, | ||
| 1565 | SHOW_SCOPE_GLOBAL}, | ||
| 1566 | {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1567 | /* Encryption */ | ||
| 1568 | {"encryption_rotation_pages_read_from_cache", | ||
| 1569 | (char *)&export_vars.innodb_encryption_rotation_pages_read_from_cache, | ||
| 1570 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1571 | {"encryption_rotation_pages_read_from_disk", | ||
| 1572 | (char *)&export_vars.innodb_encryption_rotation_pages_read_from_disk, | ||
| 1573 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1574 | {"encryption_rotation_pages_modified", | ||
| 1575 | (char *)&export_vars.innodb_encryption_rotation_pages_modified, SHOW_LONG, | ||
| 1576 | SHOW_SCOPE_GLOBAL}, | ||
| 1577 | {"encryption_rotation_pages_flushed", | ||
| 1578 | (char *)&export_vars.innodb_encryption_rotation_pages_flushed, SHOW_LONG, | ||
| 1579 | SHOW_SCOPE_GLOBAL}, | ||
| 1580 | {"encryption_rotation_estimated_iops", | ||
| 1581 | (char *)&export_vars.innodb_encryption_rotation_estimated_iops, SHOW_LONG, | ||
| 1582 | SHOW_SCOPE_GLOBAL}, | ||
| 1583 | {"encryption_key_rotation_list_length", | ||
| 1584 | (char *)&export_vars.innodb_key_rotation_list_length, SHOW_LONGLONG, | ||
| 1585 | SHOW_SCOPE_GLOBAL}, | ||
| 1586 | {"num_pages_encrypted", (char *)&export_vars.innodb_pages_encrypted, | ||
| 1587 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1588 | {"num_pages_decrypted", (char *)&export_vars.innodb_pages_decrypted, | ||
| 1589 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1590 | {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}}; | ||
| 1591 | |||
| 1592 | /** Handling the shared INNOBASE_SHARE structure that is needed to provide table | ||
| 1593 | locking. Register the table name if it doesn't exist in the hash table. */ | ||
| 1594 | static INNOBASE_SHARE *get_share( | ||
| 1595 | const char *table_name); /*!< in: table to lookup */ | ||
| 1596 | |||
| 1597 | /** Free the shared object that was registered with get_share(). */ | ||
| 1598 | static void free_share(INNOBASE_SHARE *share); /*!< in/own: share to free */ | ||
| 1599 | |||
| 1600 | /** Calls free_share and assign nullptr to share. | ||
| 1601 | @param[in,out] share table share to free */ | ||
| 1602 | 3917077 | static void free_share_and_nullify( | |
| 1603 | INNOBASE_SHARE **share) /*!< in/own: table share to free */ | ||
| 1604 | { | ||
| 1605 | 3917077 | free_share(*share); | |
| 1606 | 3917082 | *share = nullptr; | |
| 1607 | 3917082 | } | |
| 1608 | |||
| 1609 | /** Frees a possible InnoDB trx object associated with the current THD. | ||
| 1610 | @return 0 or error number */ | ||
| 1611 | static int innobase_close_connection( | ||
| 1612 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1613 | THD *thd); /*!< in: MySQL thread handle for | ||
| 1614 | which to close the connection */ | ||
| 1615 | |||
| 1616 | /** Cancel any pending lock request associated with the current THD. */ | ||
| 1617 | static void innobase_kill_connection( | ||
| 1618 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1619 | THD *thd); /*!< in: MySQL thread handle for | ||
| 1620 | which to close the connection */ | ||
| 1621 | |||
| 1622 | /** Commits a transaction in an InnoDB database or marks an SQL statement | ||
| 1623 | ended. | ||
| 1624 | @return 0 */ | ||
| 1625 | static int innobase_commit(handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1626 | THD *thd, /*!< in: MySQL thread handle of the | ||
| 1627 | user for whom the transaction should | ||
| 1628 | be committed */ | ||
| 1629 | bool commit_trx); /*!< in: true - commit transaction | ||
| 1630 | false - the current SQL statement | ||
| 1631 | ended */ | ||
| 1632 | |||
| 1633 | /** Rolls back a transaction to a savepoint. | ||
| 1634 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 1635 | given name */ | ||
| 1636 | static int innobase_rollback(handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1637 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 1638 | of the user whose transaction should | ||
| 1639 | be rolled back */ | ||
| 1640 | bool rollback_trx); /*!< in: true - rollback entire | ||
| 1641 | transaction false - rollback | ||
| 1642 | the current statement only */ | ||
| 1643 | |||
| 1644 | /** Rolls back a transaction to a savepoint. | ||
| 1645 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 1646 | given name */ | ||
| 1647 | static int innobase_rollback_to_savepoint( | ||
| 1648 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1649 | THD *thd, /*!< in: handle to the MySQL thread of | ||
| 1650 | the user whose XA transaction should | ||
| 1651 | be rolled back to savepoint */ | ||
| 1652 | void *savepoint); /*!< in: savepoint data */ | ||
| 1653 | |||
| 1654 | /** Check whether innodb state allows to safely release MDL locks after | ||
| 1655 | rollback to savepoint. | ||
| 1656 | @return true if it is safe, false if its not safe. */ | ||
| 1657 | static bool innobase_rollback_to_savepoint_can_release_mdl( | ||
| 1658 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1659 | THD *thd); /*!< in: handle to the MySQL thread of | ||
| 1660 | the user whose XA transaction should | ||
| 1661 | be rolled back to savepoint */ | ||
| 1662 | |||
| 1663 | /** Sets a transaction savepoint. | ||
| 1664 | @return always 0, that is, always succeeds */ | ||
| 1665 | static int innobase_savepoint( | ||
| 1666 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1667 | THD *thd, /*!< in: handle to the MySQL thread of | ||
| 1668 | the user's XA transaction for which | ||
| 1669 | we need to take a savepoint */ | ||
| 1670 | void *savepoint); /*!< in: savepoint data */ | ||
| 1671 | |||
| 1672 | /** Release transaction savepoint name. | ||
| 1673 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 1674 | given name */ | ||
| 1675 | static int innobase_release_savepoint( | ||
| 1676 | handlerton *hton, /*!< in/out: handlerton for InnoDB */ | ||
| 1677 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 1678 | of the user whose transaction's | ||
| 1679 | savepoint should be released */ | ||
| 1680 | void *savepoint); /*!< in: savepoint data */ | ||
| 1681 | |||
| 1682 | /** Function for constructing an InnoDB table handler instance. | ||
| 1683 | @param[in,out] hton handlerton for InnoDB | ||
| 1684 | @param[in] table MySQL table | ||
| 1685 | @param[in] partitioned Indicates whether table is partitioned | ||
| 1686 | @param[in] mem_root memory context */ | ||
| 1687 | static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table, | ||
| 1688 | bool partitioned, MEM_ROOT *mem_root); | ||
| 1689 | |||
| 1690 | /** Retrieve table satistics. | ||
| 1691 | @param[in] db_name database name | ||
| 1692 | @param[in] table_name table name | ||
| 1693 | @param[in] se_private_id The internal id of the table | ||
| 1694 | @param[in] ts_se_private_data Tablespace SE Private data | ||
| 1695 | @param[in] tbl_se_private_data Table SE private data | ||
| 1696 | @param[in] stat_flags flags used to retrieve specific stats | ||
| 1697 | @param[in,out] stats structure to save the | ||
| 1698 | retrieved statistics | ||
| 1699 | @return false on success, true on failure */ | ||
| 1700 | static bool innobase_get_table_statistics( | ||
| 1701 | const char *db_name, const char *table_name, dd::Object_id se_private_id, | ||
| 1702 | const dd::Properties &ts_se_private_data, | ||
| 1703 | const dd::Properties &tbl_se_private_data, uint stat_flags, | ||
| 1704 | ha_statistics *stats); | ||
| 1705 | |||
| 1706 | /** Retrieve index column cardinality. | ||
| 1707 | @param[in] db_name name of schema | ||
| 1708 | @param[in] table_name name of table | ||
| 1709 | @param[in] index_name name of index | ||
| 1710 | @param[in] index_ordinal_position position of index | ||
| 1711 | @param[in] column_ordinal_position position of column in index | ||
| 1712 | @param[in] se_private_id the internal id of the table | ||
| 1713 | @param[in,out] cardinality cardinality of index column | ||
| 1714 | @retval false success | ||
| 1715 | @retval true failure */ | ||
| 1716 | static bool innobase_get_index_column_cardinality( | ||
| 1717 | const char *db_name, const char *table_name, const char *index_name, | ||
| 1718 | uint index_ordinal_position, uint column_ordinal_position, | ||
| 1719 | dd::Object_id se_private_id, ulonglong *cardinality); | ||
| 1720 | |||
| 1721 | /** Retrieve ha_tablespace_statistics for the tablespace. | ||
| 1722 | |||
| 1723 | @param tablespace_name Tablespace_name | ||
| 1724 | @param file_name Data file name. | ||
| 1725 | @param ts_se_private_data Tablespace SE private data. | ||
| 1726 | @param[out] stats Contains tablespace | ||
| 1727 | statistics read from SE. | ||
| 1728 | @return false on success, true on failure */ | ||
| 1729 | static bool innobase_get_tablespace_statistics( | ||
| 1730 | const char *tablespace_name, const char *file_name, | ||
| 1731 | const dd::Properties &ts_se_private_data, ha_tablespace_statistics *stats); | ||
| 1732 | |||
| 1733 | static bool innobase_is_tablespace_keyring_pre_v3_encrypted( | ||
| 1734 | const dd::Tablespace &tablespace, int &error); | ||
| 1735 | /** Retrieve the tablespace type. | ||
| 1736 | |||
| 1737 | @param space Tablespace object. | ||
| 1738 | @param[out] space_type Tablespace category. | ||
| 1739 | @return false on success, true on failure */ | ||
| 1740 | static bool innobase_get_tablespace_type(const dd::Tablespace &space, | ||
| 1741 | Tablespace_type *space_type); | ||
| 1742 | |||
| 1743 | /** Get the tablespace type given the name. | ||
| 1744 | |||
| 1745 | @param[in] tablespace_name tablespace name | ||
| 1746 | @param[out] space_type type of space | ||
| 1747 | |||
| 1748 | @return Operation status. | ||
| 1749 | @retval false on success and true for failure. | ||
| 1750 | */ | ||
| 1751 | static bool innobase_get_tablespace_type_by_name(const char *tablespace_name, | ||
| 1752 | Tablespace_type *space_type); | ||
| 1753 | |||
| 1754 | /** Perform post-commit/rollback cleanup after DDL statement. | ||
| 1755 | @param[in,out] thd connection thread */ | ||
| 1756 | static void innobase_post_ddl(THD *thd); | ||
| 1757 | |||
| 1758 | /** Check if types of child and parent columns in foreign key are compatible. | ||
| 1759 | @param[in] child_column_type Child column type description. | ||
| 1760 | @param[in] parent_column_type Parent column type description. | ||
| 1761 | @param[in] check_charsets Indicates whether we need to check | ||
| 1762 | that charsets of string columns | ||
| 1763 | match. Which is true in most cases. | ||
| 1764 | @return True if types are compatible, False if not. */ | ||
| 1765 | static bool innodb_check_fk_column_compat( | ||
| 1766 | const Ha_fk_column_type *child_column_type, | ||
| 1767 | const Ha_fk_column_type *parent_column_type, bool check_charsets); | ||
| 1768 | |||
| 1769 | /** @brief Initialize the default value of innodb_commit_concurrency. | ||
| 1770 | |||
| 1771 | Once InnoDB is running, the innodb_commit_concurrency must not change | ||
| 1772 | from zero to nonzero. (Bug #42101) | ||
| 1773 | |||
| 1774 | The initial default value is 0, and without this extra initialization, | ||
| 1775 | SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter | ||
| 1776 | to 0, even if it was initially set to nonzero at the command line | ||
| 1777 | or configuration file. */ | ||
| 1778 | static void innobase_commit_concurrency_init_default(); | ||
| 1779 | |||
| 1780 | /** This function is used to prepare an X/Open XA distributed transaction. | ||
| 1781 | @return 0 or error number */ | ||
| 1782 | static int innobase_xa_prepare(handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 1783 | THD *thd, /*!< in: handle to the MySQL thread of | ||
| 1784 | the user whose XA transaction should | ||
| 1785 | be prepared */ | ||
| 1786 | bool all); /*!< in: true - prepare transaction | ||
| 1787 | false - the current SQL statement | ||
| 1788 | ended */ | ||
| 1789 | /** This function is used to recover X/Open XA distributed transactions. | ||
| 1790 | @return number of prepared transactions stored in xid_list */ | ||
| 1791 | static int innobase_xa_recover( | ||
| 1792 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 1793 | XA_recover_txn *txn_list, /*!< in/out: prepared transactions */ | ||
| 1794 | uint len, /*!< in: number of slots in xid_list */ | ||
| 1795 | MEM_ROOT *mem_root); /*!< in: memory for table names */ | ||
| 1796 | /** Find prepared transactions that are marked as prepared in TC, for recovery | ||
| 1797 | purposes. | ||
| 1798 | @param[in] hton InnoDB handlerton | ||
| 1799 | @param[in,out] xa_list prepared transactions state | ||
| 1800 | @return 0 if successful or error number */ | ||
| 1801 | static int innobase_xa_recover_prepared_in_tc(handlerton *hton, | ||
| 1802 | Xa_state_list &xa_list); | ||
| 1803 | /** This function is used to commit one X/Open XA distributed transaction | ||
| 1804 | which is in the prepared state | ||
| 1805 | @return 0 or error number */ | ||
| 1806 | static xa_status_code innobase_commit_by_xid( | ||
| 1807 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 1808 | XID *xid); /*!< in: X/Open XA transaction | ||
| 1809 | identification */ | ||
| 1810 | /** This function is used to rollback one X/Open XA distributed transaction | ||
| 1811 | which is in the prepared state | ||
| 1812 | @return 0 or error number */ | ||
| 1813 | static xa_status_code innobase_rollback_by_xid( | ||
| 1814 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 1815 | XID *xid); /*!< in: X/Open XA transaction | ||
| 1816 | identification */ | ||
| 1817 | /** This function is used to write mark an X/Open XA distributed transaction | ||
| 1818 | as been prepared in the server transaction coordinator | ||
| 1819 | @param[in] hton InnoDB handlerton | ||
| 1820 | @param[in] thd handle to the MySQL thread of the user whose XA transaction | ||
| 1821 | should be prepared | ||
| 1822 | @return 0 or error number */ | ||
| 1823 | static int innobase_set_prepared_in_tc(handlerton *hton, THD *thd); | ||
| 1824 | /** Mark an X/Open XA distributed transaction | ||
| 1825 | as been prepared in the server transaction coordinator | ||
| 1826 | @param[in] hton InnoDB handlerton | ||
| 1827 | @param[in] xid X/Open XA transaction identification the MySQL thread of the | ||
| 1828 | user whosefo the XA transaction that should be prepared | ||
| 1829 | @return XA_OK or error number */ | ||
| 1830 | static xa_status_code innobase_set_prepared_in_tc_by_xid(handlerton *hton, | ||
| 1831 | XID *xid); | ||
| 1832 | /** Checks if the file name is reserved in InnoDB. Currently | ||
| 1833 | redo log file names from the old redo format (ib_logfile*) | ||
| 1834 | are reserved. There is no need to reserve file names from the | ||
| 1835 | newer redo formats, because they start with '#'. | ||
| 1836 | @return true if the name is reserved | ||
| 1837 | @param[in] hton handlerton of InnoDB | ||
| 1838 | @param[in] name Name of the database */ | ||
| 1839 | static bool innobase_check_reserved_file_name(handlerton *hton, | ||
| 1840 | const char *name); | ||
| 1841 | /** Check tablespace name validity. | ||
| 1842 | @param[in] ts_cmd whether this is tablespace DDL or not | ||
| 1843 | @param[in] name name to check | ||
| 1844 | @retval false invalid name | ||
| 1845 | @retval true valid name */ | ||
| 1846 | static bool innobase_is_valid_tablespace_name(ts_command_type ts_cmd, | ||
| 1847 | const char *name); | ||
| 1848 | |||
| 1849 | /** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces. | ||
| 1850 | @param[in] hton Handlerton of InnoDB | ||
| 1851 | @param[in] thd Connection | ||
| 1852 | @param[in] alter_info Describes the command and how to do it. | ||
| 1853 | @param[in] old_ts_def Old version of dd::Tablespace object for the | ||
| 1854 | tablespace. | ||
| 1855 | @param[in,out] new_ts_def New version of dd::Tablespace object for the | ||
| 1856 | tablespace. Can be adjusted by SE. Changes will be persisted in the | ||
| 1857 | data-dictionary at statement commit. | ||
| 1858 | @return MySQL error code*/ | ||
| 1859 | static int innobase_alter_tablespace(handlerton *hton, THD *thd, | ||
| 1860 | st_alter_tablespace *alter_info, | ||
| 1861 | const dd::Tablespace *old_ts_def, | ||
| 1862 | dd::Tablespace *new_ts_def); | ||
| 1863 | |||
| 1864 | /** | ||
| 1865 | Get tablespace datafile name extension. | ||
| 1866 | */ | ||
| 1867 | static const char *innobase_get_tablespace_filename_ext(); | ||
| 1868 | |||
| 1869 | /** Free tablespace resources. */ | ||
| 1870 | 8368 | static void innodb_space_shutdown() { | |
| 1871 |
1/2✓ Branch 0 taken 8368 times.
✗ Branch 1 not taken.
|
8368 | DBUG_TRACE; |
| 1872 | |||
| 1873 |
1/2✓ Branch 0 taken 8368 times.
✗ Branch 1 not taken.
|
8368 | srv_sys_space.shutdown(); |
| 1874 |
2/2✓ Branch 0 taken 8270 times.
✓ Branch 1 taken 98 times.
|
8368 | if (srv_tmp_space.get_sanity_check_status()) { |
| 1875 |
1/2✓ Branch 0 taken 8270 times.
✗ Branch 1 not taken.
|
8270 | fil_space_close(srv_tmp_space.space_id()); |
| 1876 |
1/2✓ Branch 0 taken 8270 times.
✗ Branch 1 not taken.
|
8270 | srv_tmp_space.delete_files(); |
| 1877 | } | ||
| 1878 |
1/2✓ Branch 0 taken 8368 times.
✗ Branch 1 not taken.
|
8368 | srv_tmp_space.shutdown(); |
| 1879 | 8368 | } | |
| 1880 | |||
| 1881 | /** Shut down InnoDB after the Global Data Dictionary has been shut down. | ||
| 1882 | @see innodb_pre_dd_shutdown() | ||
| 1883 | @retval 0 always */ | ||
| 1884 | 8361 | static int innodb_shutdown(handlerton *, ha_panic_function) { | |
| 1885 |
1/2✓ Branch 0 taken 8361 times.
✗ Branch 1 not taken.
|
8361 | DBUG_TRACE; |
| 1886 | |||
| 1887 |
2/2✓ Branch 0 taken 8267 times.
✓ Branch 1 taken 94 times.
|
8361 | if (innodb_inited) { |
| 1888 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | log_pfs_delete_tables(); |
| 1889 | |||
| 1890 | 8267 | innodb_inited = false; | |
| 1891 | 8267 | ut::delete_(innobase_open_tables); | |
| 1892 | 8267 | innobase_open_tables = nullptr; | |
| 1893 | |||
| 1894 |
2/2✓ Branch 0 taken 8295 times.
✓ Branch 1 taken 8267 times.
|
16562 | for (auto file : innobase_sys_files) { |
| 1895 | 8295 | ut::delete_(file); | |
| 1896 | } | ||
| 1897 | 8267 | innobase_sys_files.clear(); | |
| 1898 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | innobase_sys_files.shrink_to_fit(); |
| 1899 | |||
| 1900 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | mutex_free(&master_key_id_mutex); |
| 1901 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | srv_shutdown(); |
| 1902 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | innodb_space_shutdown(); |
| 1903 | |||
| 1904 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | mysql_mutex_destroy(&innobase_share_mutex); |
| 1905 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | mysql_mutex_destroy(&commit_cond_m); |
| 1906 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | mysql_cond_destroy(&commit_cond); |
| 1907 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | mysql_mutex_destroy(&resume_encryption_cond_m); |
| 1908 |
1/2✓ Branch 0 taken 8267 times.
✗ Branch 1 not taken.
|
8267 | mysql_cond_destroy(&resume_encryption_cond); |
| 1909 | } | ||
| 1910 | |||
| 1911 |
1/2✓ Branch 0 taken 8361 times.
✗ Branch 1 not taken.
|
8361 | os_event_global_destroy(); |
| 1912 | |||
| 1913 |
1/2✓ Branch 0 taken 8361 times.
✗ Branch 1 not taken.
|
8361 | innobase::component_services::deinitialize_service_handles(); |
| 1914 | |||
| 1915 | 8361 | return 0; | |
| 1916 | 8361 | } | |
| 1917 | |||
| 1918 | /** Shut down all InnoDB background tasks that may access | ||
| 1919 | the Global Data Dictionary, before the Global Data Dictionary | ||
| 1920 | and the rest of InnoDB have been shut down. | ||
| 1921 | @see dd::shutdown() | ||
| 1922 | @see innodb_shutdown() */ | ||
| 1923 | 8374 | static void innodb_pre_dd_shutdown(handlerton *) { | |
| 1924 |
2/2✓ Branch 0 taken 8280 times.
✓ Branch 1 taken 94 times.
|
8374 | if (innodb_inited) { |
| 1925 | 8280 | srv_pre_dd_shutdown(); | |
| 1926 | } | ||
| 1927 | 8361 | } | |
| 1928 | |||
| 1929 | /** Stores the current binlog coordinates in the trx system header. | ||
| 1930 | @param[in] hton InnoDB handlerton | ||
| 1931 | @param[in] thd MySQL thrad handle */ | ||
| 1932 | static int innobase_store_binlog_info(handlerton *hton, THD *thd) noexcept; | ||
| 1933 | |||
| 1934 | /** Creates an InnoDB transaction struct for the thd if it does not yet have | ||
| 1935 | one. Starts a new InnoDB transaction if a transaction is not yet started. And | ||
| 1936 | assigns a new snapshot for a consistent read if the transaction does not yet | ||
| 1937 | have one. | ||
| 1938 | @return 0 */ | ||
| 1939 | static int innobase_start_trx_and_assign_read_view( | ||
| 1940 | handlerton *hton, /* in: InnoDB handlerton */ | ||
| 1941 | THD *thd); /* in: MySQL thread handle of the | ||
| 1942 | user for whom the transaction should | ||
| 1943 | be committed */ | ||
| 1944 | |||
| 1945 | /** Creates an InnoDB transaction struct for the thd if it does not | ||
| 1946 | yet have one. Starts a new InnoDB transaction if a transaction is not | ||
| 1947 | yet started. And clones snapshot for a consistent read from another | ||
| 1948 | session, if it has one. | ||
| 1949 | @param[in] hton InnoDB handlerton | ||
| 1950 | @param[in] thd MySQL thread handle of the user for whom the | ||
| 1951 | transaction should be committed | ||
| 1952 | @param[in] from_thd MySQL thread handle of the user session from | ||
| 1953 | which the consistent read should be cloned | ||
| 1954 | @return 0 */ | ||
| 1955 | static int innobase_start_trx_and_clone_read_view(handlerton *hton, THD *thd, | ||
| 1956 | THD *from_thd); | ||
| 1957 | |||
| 1958 | /** Flush InnoDB redo logs to the file system. | ||
| 1959 | @param[in] hton InnoDB handlerton | ||
| 1960 | @param[in] binlog_group_flush true if we got invoked by binlog | ||
| 1961 | group commit during flush stage, false in other cases. | ||
| 1962 | @return false */ | ||
| 1963 | static bool innobase_flush_logs(handlerton *hton, bool binlog_group_flush); | ||
| 1964 | |||
| 1965 | /** Implements the SHOW ENGINE INNODB STATUS command. Sends the output of the | ||
| 1966 | InnoDB Monitor to the client. | ||
| 1967 | @param[in] hton the innodb handlerton | ||
| 1968 | @param[in] thd the MySQL query thread of the caller | ||
| 1969 | @param[in] stat_print print function | ||
| 1970 | @return 0 on success */ | ||
| 1971 | static int innodb_show_status(handlerton *hton, THD *thd, | ||
| 1972 | stat_print_fn *stat_print); | ||
| 1973 | |||
| 1974 | /** Implements Log_resource lock. | ||
| 1975 | @param[in] hton the innodb handlerton | ||
| 1976 | @return false on success */ | ||
| 1977 | static bool innobase_lock_hton_log(handlerton *hton); | ||
| 1978 | |||
| 1979 | /** Implements Log_resource unlock. | ||
| 1980 | @param[in] hton the innodb handlerton | ||
| 1981 | @return false on success */ | ||
| 1982 | static bool innobase_unlock_hton_log(handlerton *hton); | ||
| 1983 | |||
| 1984 | /** Implements Log_resource collect_info. | ||
| 1985 | @param[in] hton the innodb handlerton | ||
| 1986 | @param[in] json the JSON dom to receive the log info | ||
| 1987 | @return false on success */ | ||
| 1988 | static bool innobase_collect_hton_log_info(handlerton *hton, Json_dom *json); | ||
| 1989 | |||
| 1990 | /** Return 0 on success and non-zero on failure. Note: the bool return type | ||
| 1991 | seems to be abused here, should be an int. | ||
| 1992 | @param[in] hton the innodb handlerton | ||
| 1993 | @param[in] thd the MySQL query thread of the caller | ||
| 1994 | @param[in] stat_print print function | ||
| 1995 | @param[in] stat_type status to show */ | ||
| 1996 | static bool innobase_show_status(handlerton *hton, THD *thd, | ||
| 1997 | stat_print_fn *stat_print, | ||
| 1998 | enum ha_stat_type stat_type); | ||
| 1999 | |||
| 2000 | /** Parse and enable InnoDB monitor counters during server startup. | ||
| 2001 | User can enable monitor counters/groups by specifying | ||
| 2002 | "loose-innodb_monitor_enable = monitor_name1;monitor_name2..." | ||
| 2003 | in server configuration file or at the command line. */ | ||
| 2004 | static void innodb_enable_monitor_at_startup( | ||
| 2005 | char *str); /*!< in: monitor counter enable list */ | ||
| 2006 | |||
| 2007 | /** Fill handlerton based INFORMATION_SCHEMA tables. | ||
| 2008 | @param[in] hton (unused) Handle to the handlerton structure | ||
| 2009 | @param[in] thd Thread/connection descriptor | ||
| 2010 | @param[in,out] tables Information Schema tables to fill | ||
| 2011 | @param[in] idx_cond (unused) Intended for conditional pushdown | ||
| 2012 | @param[in] idx Table id that indicates which I_S table to fill | ||
| 2013 | @return Operation status */ | ||
| 2014 | 4 | static int innobase_fill_i_s_table(handlerton *hton [[maybe_unused]], | |
| 2015 | THD *thd [[maybe_unused]], | ||
| 2016 | TABLE_LIST *tables [[maybe_unused]], | ||
| 2017 | Item *idx_cond [[maybe_unused]], | ||
| 2018 | enum_schema_tables idx) { | ||
| 2019 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | assert(idx == SCH_TABLESPACES); |
| 2020 | |||
| 2021 | /** InnoDB does not implement I_S.TABLESPACES */ | ||
| 2022 | |||
| 2023 | 4 | return (0); | |
| 2024 | } | ||
| 2025 | |||
| 2026 | /** Store doc_id value into FTS_DOC_ID field | ||
| 2027 | @param[in,out] tbl table containing FULLTEXT index | ||
| 2028 | @param[in] doc_id FTS_DOC_ID value */ | ||
| 2029 | 134 | static void innobase_fts_store_docid(TABLE *tbl, ulonglong doc_id) { | |
| 2030 | 134 | my_bitmap_map *old_map = dbug_tmp_use_all_columns(tbl, tbl->write_set); | |
| 2031 | |||
| 2032 | 134 | tbl->fts_doc_id_field->store(static_cast<longlong>(doc_id), true); | |
| 2033 | |||
| 2034 | 134 | dbug_tmp_restore_column_map(tbl->write_set, old_map); | |
| 2035 | 134 | } | |
| 2036 | |||
| 2037 | /** Check for a valid value of innobase_commit_concurrency. | ||
| 2038 | @return 0 for valid innodb_commit_concurrency */ | ||
| 2039 | 17 | static int innobase_commit_concurrency_validate( | |
| 2040 | THD *, /*!< in: thread handle */ | ||
| 2041 | SYS_VAR *, /*!< in: pointer to system | ||
| 2042 | variable */ | ||
| 2043 | void *save, /*!< out: immediate result | ||
| 2044 | for update function */ | ||
| 2045 | struct st_mysql_value *value) /*!< in: incoming string */ | ||
| 2046 | { | ||
| 2047 | long long intbuf; | ||
| 2048 | ulong commit_concurrency; | ||
| 2049 | |||
| 2050 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | DBUG_TRACE; |
| 2051 | |||
| 2052 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
17 | if (value->val_int(value, &intbuf)) { |
| 2053 | /* The value is NULL. That is invalid. */ | ||
| 2054 | ✗ | return 1; | |
| 2055 | } | ||
| 2056 | |||
| 2057 | 17 | *reinterpret_cast<ulong *>(save) = commit_concurrency = | |
| 2058 | 17 | static_cast<ulong>(intbuf); | |
| 2059 | |||
| 2060 | /* Allow the value to be updated, as long as it remains zero | ||
| 2061 | or nonzero. */ | ||
| 2062 | 17 | return !(!commit_concurrency == !innobase_commit_concurrency); | |
| 2063 | 17 | } | |
| 2064 | |||
| 2065 | /** Function for constructing an InnoDB table handler instance. | ||
| 2066 | @param[in,out] hton handlerton for InnoDB | ||
| 2067 | @param[in] table MySQL table | ||
| 2068 | @param[in] partitioned Indicates whether table is partitioned | ||
| 2069 | @param[in] mem_root memory context */ | ||
| 2070 | 9236908 | static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table, | |
| 2071 | bool partitioned, MEM_ROOT *mem_root) { | ||
| 2072 |
2/2✓ Branch 0 taken 103880 times.
✓ Branch 1 taken 9133028 times.
|
9236908 | if (partitioned) { |
| 2073 |
2/4✓ Branch 0 taken 103881 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 103881 times.
✗ Branch 3 not taken.
|
103880 | ha_innopart *file = new (mem_root) ha_innopart(hton, table); |
| 2074 |
3/6✓ Branch 0 taken 103881 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 103881 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 103881 times.
|
103881 | if (file && file->init_partitioning(mem_root)) { |
| 2075 | ✗ | destroy(file); | |
| 2076 | ✗ | return (nullptr); | |
| 2077 | } | ||
| 2078 | 103881 | return (file); | |
| 2079 | } | ||
| 2080 | |||
| 2081 |
2/4✓ Branch 0 taken 9133048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9133047 times.
✗ Branch 3 not taken.
|
9133028 | return (new (mem_root) ha_innobase(hton, table)); |
| 2082 | } | ||
| 2083 | |||
| 2084 | /* General functions */ | ||
| 2085 | |||
| 2086 | /** Returns true if the thread is the replication thread on the slave | ||
| 2087 | server. Used in srv_conc_enter_innodb() to determine if the thread | ||
| 2088 | should be allowed to enter InnoDB - the replication thread is treated | ||
| 2089 | differently than other threads. Also used in | ||
| 2090 | srv_conc_force_exit_innodb(). | ||
| 2091 | @return true if thd is the replication thread */ | ||
| 2092 | 157387 | bool thd_is_replication_slave_thread(THD *thd) /*!< in: thread handle */ | |
| 2093 | { | ||
| 2094 |
3/4✓ Branch 0 taken 157387 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 540 times.
✓ Branch 3 taken 156847 times.
|
157387 | return thd != nullptr && thd_slave_thread(thd); |
| 2095 | } | ||
| 2096 | |||
| 2097 | /** Gets information on the durability property requested by thread. | ||
| 2098 | Used when writing either a prepare or commit record to the log | ||
| 2099 | buffer. @return the durability property. */ | ||
| 2100 | 7105125 | enum durability_properties thd_requested_durability( | |
| 2101 | const THD *thd) /*!< in: thread handle */ | ||
| 2102 | { | ||
| 2103 | 7105125 | return (thd_get_durability_property(thd)); | |
| 2104 | } | ||
| 2105 | |||
| 2106 | /** Returns true if transaction should be flagged as read-only. | ||
| 2107 | @return true if the thd is marked as read-only */ | ||
| 2108 | 17400167 | bool thd_trx_is_read_only(THD *thd) /*!< in: thread handle */ | |
| 2109 | { | ||
| 2110 |
4/4✓ Branch 0 taken 17229889 times.
✓ Branch 1 taken 170278 times.
✓ Branch 2 taken 11942231 times.
✓ Branch 3 taken 5287647 times.
|
17400167 | return (thd != nullptr && thd_tx_is_read_only(thd)); |
| 2111 | } | ||
| 2112 | |||
| 2113 | /** | ||
| 2114 | Check if the transaction can be rolled back | ||
| 2115 | @param[in] requestor Session requesting the lock | ||
| 2116 | @param[in] holder Session that holds the lock | ||
| 2117 | @return the session that will be rolled back, null don't care */ | ||
| 2118 | |||
| 2119 | ✗ | THD *thd_trx_arbitrate(THD *requestor, THD *holder) { | |
| 2120 | /* Non-user (thd==0) transactions by default can't rollback, in | ||
| 2121 | practice DDL transactions should never rollback and that's because | ||
| 2122 | they should never wait on table/record locks either */ | ||
| 2123 | |||
| 2124 | ✗ | ut_a(holder != nullptr); | |
| 2125 | ✗ | ut_a(holder != requestor); | |
| 2126 | |||
| 2127 | ✗ | THD *victim = thd_tx_arbitrate(requestor, holder); | |
| 2128 | |||
| 2129 | ✗ | ut_a(victim == nullptr || victim == requestor || victim == holder); | |
| 2130 | |||
| 2131 | ✗ | return (victim); | |
| 2132 | } | ||
| 2133 | |||
| 2134 | /** | ||
| 2135 | @param[in] thd Session to check | ||
| 2136 | @return the priority */ | ||
| 2137 | |||
| 2138 | 394364547 | int thd_trx_priority(THD *thd) { | |
| 2139 |
1/2✓ Branch 0 taken 394364745 times.
✗ Branch 1 not taken.
|
394364547 | return (thd == nullptr ? 0 : thd_tx_priority(thd)); |
| 2140 | } | ||
| 2141 | |||
| 2142 | /** Check if the transaction is an auto-commit transaction. true also | ||
| 2143 | implies that it is a SELECT (read-only) transaction. | ||
| 2144 | @return true if the transaction is an auto commit read-only transaction. */ | ||
| 2145 | 19653737 | bool thd_trx_is_auto_commit(THD *thd) /*!< in: thread handle, can be NULL */ | |
| 2146 | { | ||
| 2147 | 17230267 | return thd != nullptr && | |
| 2148 |
4/4✓ Branch 0 taken 17230379 times.
✓ Branch 1 taken 2423358 times.
✓ Branch 2 taken 16071904 times.
✓ Branch 3 taken 1158363 times.
|
35725632 | !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) && |
| 2149 |
2/2✓ Branch 0 taken 12609459 times.
✓ Branch 1 taken 3462436 times.
|
35725520 | thd_is_query_block(thd); |
| 2150 | } | ||
| 2151 | |||
| 2152 | extern "C" long long thd_start_time(const THD *thd); | ||
| 2153 | |||
| 2154 | 17228998 | std::chrono::system_clock::time_point thd_start_time(THD *) { | |
| 2155 | // FIXME: This function should be added to the server code. | ||
| 2156 | // return(thd_start_time(thd)); | ||
| 2157 | 17228998 | return std::chrono::system_clock::now(); | |
| 2158 | } | ||
| 2159 | |||
| 2160 | /** Enter InnoDB engine after checking the max number of user threads | ||
| 2161 | allowed, else the thread is put into sleep. | ||
| 2162 | @param[in,out] prebuilt row prebuilt handler | ||
| 2163 | @return InnoDB error code. */ | ||
| 2164 | 537989476 | static inline dberr_t innobase_srv_conc_enter_innodb(row_prebuilt_t *prebuilt) { | |
| 2165 | /* We rely on server to do external_lock(F_UNLCK) to reset the | ||
| 2166 | srv_conc.n_active counter. */ | ||
| 2167 |
2/2✓ Branch 0 taken 226135962 times.
✓ Branch 1 taken 311855151 times.
|
537989476 | if (prebuilt->skip_concurrency_ticket()) { |
| 2168 | 226135962 | return DB_SUCCESS; | |
| 2169 | } | ||
| 2170 | |||
| 2171 | #ifdef WITH_WSREP | ||
| 2172 | // innodb_thread_concurreny limit how many thread can work in innodb | ||
| 2173 | // at any given time. This limit is not applicable to wsrep-applier | ||
| 2174 | // threads given they are high priority threads. | ||
| 2175 |
4/4✓ Branch 0 taken 26139490 times.
✓ Branch 1 taken 285715306 times.
✓ Branch 2 taken 3470521 times.
✓ Branch 3 taken 308384350 times.
|
337994716 | if (wsrep_on(prebuilt->trx->mysql_thd) && |
| 2176 |
2/2✓ Branch 0 taken 3470522 times.
✓ Branch 1 taken 22669043 times.
|
26139490 | wsrep_thd_is_BF(prebuilt->trx->mysql_thd, false)) |
| 2177 | 3470521 | return DB_SUCCESS; | |
| 2178 | #endif /* WITH_WSREP */ | ||
| 2179 | |||
| 2180 | 308384350 | dberr_t err = DB_SUCCESS; | |
| 2181 | 308384350 | trx_t *trx = prebuilt->trx; | |
| 2182 | |||
| 2183 |
2/2✓ Branch 0 taken 41353 times.
✓ Branch 1 taken 308342997 times.
|
308384350 | if (srv_thread_concurrency) { |
| 2184 |
2/2✓ Branch 0 taken 39426 times.
✓ Branch 1 taken 1927 times.
|
41353 | if (trx->n_tickets_to_enter_innodb > 0) { |
| 2185 | /* If trx has 'free tickets' to enter the engine left, | ||
| 2186 | then use one such ticket */ | ||
| 2187 | |||
| 2188 | 39426 | --trx->n_tickets_to_enter_innodb; | |
| 2189 | |||
| 2190 |
2/4✓ Branch 0 taken 1928 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1927 times.
|
3855 | } else if (trx->mysql_thd != nullptr && |
| 2191 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1928 times.
|
1928 | thd_is_replication_slave_thread(trx->mysql_thd)) { |
| 2192 | ✗ | ut::wait_for( | |
| 2193 | ✗ | [&]() { | |
| 2194 | ✗ | return srv_conc_get_active_threads() < | |
| 2195 | ✗ | (int32_t)srv_thread_concurrency; | |
| 2196 | }, | ||
| 2197 | ✗ | get_srv_replication_delay()); | |
| 2198 | |||
| 2199 | } else { | ||
| 2200 | 1927 | err = srv_conc_enter_innodb(prebuilt); | |
| 2201 | } | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | 308384351 | return err; | |
| 2205 | } | ||
| 2206 | |||
| 2207 | /** Note that the thread wants to leave InnoDB only if it doesn't have | ||
| 2208 | any spare tickets. | ||
| 2209 | @param[in,out] prebuilt row prebuilt handler */ | ||
| 2210 | 537990997 | static inline void innobase_srv_conc_exit_innodb(row_prebuilt_t *prebuilt) { | |
| 2211 | #ifdef WITH_WSREP | ||
| 2212 | // innodb_thread_concurreny limit how many thread can work in innodb | ||
| 2213 | // at any given time. This limit is not applicable to wsrep-applier | ||
| 2214 | // threads given they are high priority threads. | ||
| 2215 |
5/6✓ Branch 0 taken 537991922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32264663 times.
✓ Branch 3 taken 505727259 times.
✓ Branch 4 taken 4983676 times.
✓ Branch 5 taken 533008246 times.
|
570255660 | if (wsrep_on(prebuilt->trx->mysql_thd) && |
| 2216 |
3/4✓ Branch 0 taken 32264663 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4983676 times.
✓ Branch 3 taken 27280987 times.
|
32264663 | wsrep_thd_is_BF(prebuilt->trx->mysql_thd, false)) |
| 2217 | 229606616 | return; | |
| 2218 | #endif /* WITH_WSREP */ | ||
| 2219 | |||
| 2220 | /* We rely on server to do external_lock(F_UNLCK) to reset the | ||
| 2221 | srv_conc.n_active counter. */ | ||
| 2222 |
3/4✓ Branch 0 taken 533008341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224622940 times.
✓ Branch 3 taken 308385401 times.
|
533008246 | if (prebuilt->skip_concurrency_ticket()) { |
| 2223 | 224622940 | return; | |
| 2224 | } | ||
| 2225 | |||
| 2226 | 308385401 | trx_t *trx = prebuilt->trx; | |
| 2227 | #ifdef UNIV_DEBUG | ||
| 2228 | 308385401 | btrsea_sync_check check(trx->has_search_latch); | |
| 2229 | |||
| 2230 |
2/4✓ Branch 0 taken 308385513 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 308385426 times.
|
308385548 | ut_ad(!sync_check_iterate(check)); |
| 2231 | #endif /* UNIV_DEBUG */ | ||
| 2232 | |||
| 2233 | /* This is to avoid making an unnecessary function call. */ | ||
| 2234 |
2/2✓ Branch 0 taken 41352 times.
✓ Branch 1 taken 308344074 times.
|
308385426 | if (trx->declared_to_be_inside_innodb && |
| 2235 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 41349 times.
|
41352 | trx->n_tickets_to_enter_innodb == 0) { |
| 2236 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | srv_conc_force_exit_innodb(trx); |
| 2237 | } | ||
| 2238 | 308385426 | } | |
| 2239 | |||
| 2240 | /** Force a thread to leave InnoDB even if it has spare tickets. */ | ||
| 2241 | 156971059 | static inline void innobase_srv_conc_force_exit_innodb( | |
| 2242 | trx_t *trx) /*!< in: transaction handle */ | ||
| 2243 | { | ||
| 2244 | #ifdef UNIV_DEBUG | ||
| 2245 | 156971059 | btrsea_sync_check check(trx->has_search_latch); | |
| 2246 | |||
| 2247 |
2/4✓ Branch 0 taken 156971459 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 156971086 times.
|
156971285 | ut_ad(!sync_check_iterate(check)); |
| 2248 | #endif /* UNIV_DEBUG */ | ||
| 2249 | |||
| 2250 | /* This is to avoid making an unnecessary function call. */ | ||
| 2251 |
2/2✓ Branch 0 taken 1923 times.
✓ Branch 1 taken 156969163 times.
|
156971086 | if (trx->declared_to_be_inside_innodb) { |
| 2252 |
1/2✓ Branch 0 taken 1924 times.
✗ Branch 1 not taken.
|
1923 | srv_conc_force_exit_innodb(trx); |
| 2253 | } | ||
| 2254 | 156971087 | } | |
| 2255 | |||
| 2256 | /** Returns the NUL terminated value of glob_hostname. | ||
| 2257 | @return pointer to glob_hostname. */ | ||
| 2258 | 644 | const char *server_get_hostname() { return (glob_hostname); } | |
| 2259 | |||
| 2260 | /** Returns true if the transaction this thread is processing has edited | ||
| 2261 | non-transactional tables. Used by the deadlock detector when deciding | ||
| 2262 | which transaction to rollback in case of a deadlock - we try to avoid | ||
| 2263 | rolling back transactions that have edited non-transactional tables. | ||
| 2264 | @return true if non-transactional tables have been edited */ | ||
| 2265 | 392 | bool thd_has_edited_nontrans_tables(THD *thd) /*!< in: thread handle */ | |
| 2266 | { | ||
| 2267 | 392 | return thd_non_transactional_update(thd); | |
| 2268 | } | ||
| 2269 | |||
| 2270 | /** Returns true if the thread is executing a SELECT statement. | ||
| 2271 | @return true if thd is executing SELECT */ | ||
| 2272 | 16687657 | bool thd_is_query_block(const THD *thd) /*!< in: thread handle */ | |
| 2273 | { | ||
| 2274 | 16687657 | return thd_sql_command(thd) == SQLCOM_SELECT; | |
| 2275 | } | ||
| 2276 | |||
| 2277 | /** Checks sys_vars and determines if allocator should mark | ||
| 2278 | large memory segments with MADV_DONTDUMP | ||
| 2279 | @return true iff @@global.core_file AND | ||
| 2280 | NOT @@global.innodb_buffer_pool_in_core_file */ | ||
| 2281 | 9693 | bool innobase_should_madvise_buf_pool() { | |
| 2282 |
4/4✓ Branch 0 taken 8967 times.
✓ Branch 1 taken 726 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 8963 times.
|
9693 | return (test_flags & TEST_CORE_ON_SIGNAL) && !srv_buffer_pool_in_core_file; |
| 2283 | } | ||
| 2284 | |||
| 2285 | /** Make sure that core file will not be generated, as generating a core file | ||
| 2286 | might violate our promise to not dump buffer pool data, and/or might dump not | ||
| 2287 | the expected memory pages due to failure in using madvise */ | ||
| 2288 | ✗ | void innobase_disable_core_dump() { | |
| 2289 | /* TODO: There is a race condition here, as test_flags is not an atomic<> | ||
| 2290 | and there might be multiple threads calling this function | ||
| 2291 | in parallel (once for each buffer pool thread). | ||
| 2292 | One approach would be to use a loop with os_compare_and_swap_ulint | ||
| 2293 | unfortunately test_flags is defined as uint, not ulint, and we don't | ||
| 2294 | have nice portable function for dealing with uint in InnoDB. | ||
| 2295 | Moreover that would only prevent problems with mangled bits, but not | ||
| 2296 | help at all with that some other thread might be reading test_flags | ||
| 2297 | and making decisions based on observed value while we are changing it. | ||
| 2298 | The good news is that all these threads try to do the same thing: clear the | ||
| 2299 | same bit. So this happens to work. | ||
| 2300 | */ | ||
| 2301 | |||
| 2302 | ✗ | test_flags &= ~TEST_CORE_ON_SIGNAL; | |
| 2303 | } | ||
| 2304 | |||
| 2305 | 208095 | std::chrono::seconds thd_lock_wait_timeout(THD *thd) { | |
| 2306 | /* According to <mysql/plugin.h>, passing thd == NULL | ||
| 2307 | returns the global value of the session variable. */ | ||
| 2308 | 208095 | return std::chrono::seconds{THDVAR(thd, lock_wait_timeout)}; | |
| 2309 | } | ||
| 2310 | |||
| 2311 | /** Is FT ignore stopwords variable set. | ||
| 2312 | @param thd Thread object | ||
| 2313 | @return true if ft_ignore_stopwords is set, false otherwise. */ | ||
| 2314 | 4207085 | bool thd_has_ft_ignore_stopwords(THD *thd) noexcept { | |
| 2315 | 4207085 | return (THDVAR(thd, ft_ignore_stopwords)); | |
| 2316 | } | ||
| 2317 | |||
| 2318 | 20670 | void thd_set_lock_wait_time(THD *thd, | |
| 2319 | std::chrono::steady_clock::duration value) { | ||
| 2320 |
1/2✓ Branch 0 taken 20670 times.
✗ Branch 1 not taken.
|
20670 | if (thd) { |
| 2321 |
1/2✓ Branch 0 taken 20670 times.
✗ Branch 1 not taken.
|
20670 | thd_storage_lock_wait( |
| 2322 | thd, | ||
| 2323 | 41340 | std::chrono::duration_cast<std::chrono::microseconds>(value).count()); | |
| 2324 | } | ||
| 2325 | 20670 | } | |
| 2326 | |||
| 2327 | 100067 | const char *thd_innodb_tmpdir(THD *thd) { | |
| 2328 | #ifdef UNIV_DEBUG | ||
| 2329 |
2/2✓ Branch 0 taken 100013 times.
✓ Branch 1 taken 54 times.
|
100067 | if (thd != nullptr) { |
| 2330 |
1/2✓ Branch 0 taken 100013 times.
✗ Branch 1 not taken.
|
100013 | auto trx = thd_to_trx(thd); |
| 2331 | |||
| 2332 | 100013 | btrsea_sync_check check(trx->has_search_latch); | |
| 2333 | |||
| 2334 |
2/4✓ Branch 0 taken 100013 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 100013 times.
|
100013 | ut_ad(!sync_check_iterate(check)); |
| 2335 | 100013 | } | |
| 2336 | #endif /* UNIV_DEBUG */ | ||
| 2337 | |||
| 2338 | 100067 | const char *tmp_dir = THDVAR(thd, tmpdir); | |
| 2339 | |||
| 2340 |
3/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 100050 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
100067 | if (tmp_dir != nullptr && *tmp_dir == '\0') { |
| 2341 | ✗ | tmp_dir = nullptr; | |
| 2342 | } | ||
| 2343 | |||
| 2344 | 100067 | return tmp_dir; | |
| 2345 | } | ||
| 2346 | |||
| 2347 | /** Obtain the private handler of InnoDB session specific data. | ||
| 2348 | @param[in,out] thd MySQL thread handler. | ||
| 2349 | @return reference to private handler */ | ||
| 2350 | |||
| 2351 | 3417222772 | [[nodiscard]] innodb_session_t *&thd_to_innodb_session(THD *thd) { | |
| 2352 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3417222772 times.
|
3417222772 | assert(innodb_hton_ptr->slot != HA_SLOT_UNDEF); |
| 2353 | |||
| 2354 | innodb_session_t *&innodb_session = | ||
| 2355 | 3417222772 | *(innodb_session_t **)thd_ha_data(thd, innodb_hton_ptr); | |
| 2356 | |||
| 2357 |
2/2✓ Branch 0 taken 3400998259 times.
✓ Branch 1 taken 16234722 times.
|
3417232981 | if (innodb_session != nullptr) { |
| 2358 | 3400998259 | return (innodb_session); | |
| 2359 | } | ||
| 2360 | |||
| 2361 | 16234722 | innodb_session = ut::new_withkey<innodb_session_t>(UT_NEW_THIS_FILE_PSI_KEY); | |
| 2362 | 16235129 | return (innodb_session); | |
| 2363 | } | ||
| 2364 | |||
| 2365 | /** Obtain the InnoDB transaction of a MySQL thread. | ||
| 2366 | @param[in,out] thd MySQL thread handler. | ||
| 2367 | @return reference to transaction pointer */ | ||
| 2368 | |||
| 2369 | 3298746803 | [[nodiscard]] trx_t *&thd_to_trx(THD *thd) { | |
| 2370 | 3298746803 | innodb_session_t *&innodb_session = thd_to_innodb_session(thd); | |
| 2371 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3298757741 times.
|
3298764987 | ut_ad(innodb_session != nullptr); |
| 2372 | |||
| 2373 | 3298757741 | return (innodb_session->m_trx); | |
| 2374 | } | ||
| 2375 | |||
| 2376 | #ifdef WITH_WSREP | ||
| 2377 | |||
| 2378 | /** Obtain the private handler of InnoDB session specific data. | ||
| 2379 | @param[in,out] thd MySQL thread handler. | ||
| 2380 | @return reference to private handler */ | ||
| 2381 | MY_ATTRIBUTE((warn_unused_result)) | ||
| 2382 | 174 | innodb_session_t *&wsrep_thd_to_innodb_session(THD *thd) { | |
| 2383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
|
174 | assert(innodb_hton_ptr->slot != HA_SLOT_UNDEF); |
| 2384 | innodb_session_t *&innodb_session = | ||
| 2385 | 174 | *(innodb_session_t **)wsrep_thd_ha_data(thd, innodb_hton_ptr); | |
| 2386 | |||
| 2387 |
2/2✓ Branch 0 taken 147 times.
✓ Branch 1 taken 27 times.
|
174 | if (innodb_session != NULL) { |
| 2388 | 147 | return (innodb_session); | |
| 2389 | } | ||
| 2390 | |||
| 2391 | /* Ideally, each local transaction executing thread should have | ||
| 2392 | innodb_session already created but there are cases like background | ||
| 2393 | stats update thread that too takes MDL lock creating potential conflict. | ||
| 2394 | Given this is background thread it doesn't have an active transaction | ||
| 2395 | associated with it. */ | ||
| 2396 | 27 | innodb_session = ut::new_withkey<innodb_session_t>(UT_NEW_THIS_FILE_PSI_KEY); | |
| 2397 | 27 | return (innodb_session); | |
| 2398 | } | ||
| 2399 | |||
| 2400 | /** Obtain the InnoDB transaction of a MySQL thread. | ||
| 2401 | @param[in,out] thd MySQL thread handler. | ||
| 2402 | @return reference to transaction pointer */ | ||
| 2403 | MY_ATTRIBUTE((warn_unused_result)) | ||
| 2404 | 174 | trx_t *&wsrep_thd_to_trx(THD *thd) { | |
| 2405 | 174 | innodb_session_t *&innodb_session = wsrep_thd_to_innodb_session(thd); | |
| 2406 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
|
174 | ut_ad(innodb_session != NULL); |
| 2407 | |||
| 2408 | 174 | return (innodb_session->m_trx); | |
| 2409 | } | ||
| 2410 | |||
| 2411 | #endif /* WITH_WSREP */ | ||
| 2412 | |||
| 2413 | 86405 | ulong thd_parallel_read_threads(THD *thd) { | |
| 2414 | 86405 | return THDVAR(thd, parallel_read_threads); | |
| 2415 | } | ||
| 2416 | |||
| 2417 | 43913 | ulong thd_ddl_buffer_size(THD *thd) { return THDVAR(thd, ddl_buffer_size); } | |
| 2418 | |||
| 2419 | 43913 | size_t thd_ddl_threads(THD *thd) noexcept { return THDVAR(thd, ddl_threads); } | |
| 2420 | |||
| 2421 | /** Check if statement is of type INSERT .... SELECT that involves | ||
| 2422 | use of intrinsic tables. | ||
| 2423 | @param[in] user_thd thread handler | ||
| 2424 | @return true if INSERT .... SELECT statement. */ | ||
| 2425 | 71223696 | static inline bool thd_is_ins_sel_stmt(THD *user_thd) { | |
| 2426 | /* If the session involves use of intrinsic table | ||
| 2427 | and it is trying to fetch the result from non-temporary tables | ||
| 2428 | it indicates "insert .... select" statement. For non-temporary | ||
| 2429 | table this is verifed using the locked tables count but for | ||
| 2430 | intrinsic table as external_lock is not invoked this count is | ||
| 2431 | not updated. | ||
| 2432 | |||
| 2433 | Why is this needed ? | ||
| 2434 | Use of AHI is blocked if statement is insert .... select statement. */ | ||
| 2435 | 71223696 | innodb_session_t *innodb_priv = thd_to_innodb_session(user_thd); | |
| 2436 | 71224456 | return (innodb_priv->count_register_table_handler() > 0 ? true : false); | |
| 2437 | } | ||
| 2438 | |||
| 2439 | #ifdef WITH_WSREP | ||
| 2440 | static int wsrep_abort_transaction_func(handlerton *hton, THD *bf_thd, | ||
| 2441 | THD *victim_thd, bool signal); | ||
| 2442 | static int innobase_wsrep_set_checkpoint(handlerton *hton, const XID *xid); | ||
| 2443 | static int innobase_wsrep_get_checkpoint(handlerton *hton, XID *xid); | ||
| 2444 | |||
| 2445 | #endif /* WITH_WSREP */ | ||
| 2446 | |||
| 2447 | /** Add the table handler to thread cache. | ||
| 2448 | Obtain the InnoDB transaction of a MySQL thread. | ||
| 2449 | @param[in,out] table table handler | ||
| 2450 | @param[in,out] heap heap for allocating system columns. | ||
| 2451 | @param[in,out] thd MySQL thread handler */ | ||
| 2452 | 110975 | static inline void add_table_to_thread_cache(dict_table_t *table, | |
| 2453 | mem_heap_t *heap, THD *thd) { | ||
| 2454 | 110975 | dict_table_add_system_columns(table, heap); | |
| 2455 | |||
| 2456 | 110975 | dict_table_set_big_rows(table); | |
| 2457 | |||
| 2458 | 110975 | innodb_session_t *&priv = thd_to_innodb_session(thd); | |
| 2459 | 110975 | priv->register_table_handler(table->name.m_name, table); | |
| 2460 | 110975 | } | |
| 2461 | |||
| 2462 | /** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth | ||
| 2463 | time calls srv_active_wake_master_thread. This function should be used | ||
| 2464 | when a single database operation may introduce a small need for | ||
| 2465 | server utility activity, like checkpointing. */ | ||
| 2466 | 89003503 | inline void innobase_active_small(void) { | |
| 2467 | 89003503 | innobase_active_counter++; | |
| 2468 | |||
| 2469 |
2/2✓ Branch 0 taken 2776580 times.
✓ Branch 1 taken 86226923 times.
|
89003503 | if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) { |
| 2470 | 2776580 | srv_active_wake_master_thread(); | |
| 2471 | } | ||
| 2472 | 89003506 | } | |
| 2473 | |||
| 2474 | /** Converts an InnoDB error code to a MySQL error code. | ||
| 2475 | Also tells to MySQL about a possible transaction rollback inside InnoDB caused | ||
| 2476 | by a lock wait timeout or a deadlock. | ||
| 2477 | @param[in] error InnoDB error code. | ||
| 2478 | @param[in] flags InnoDB table flags or 0. | ||
| 2479 | @param[in] thd MySQL thread or NULL. | ||
| 2480 | @return MySQL error code */ | ||
| 2481 | 121239331 | int convert_error_code_to_mysql(dberr_t error, uint32_t flags, THD *thd) { | |
| 2482 |
32/48✓ Branch 0 taken 120167456 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 201 times.
✓ Branch 5 taken 1070391 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 485 times.
✓ Branch 11 taken 427 times.
✓ Branch 12 taken 106 times.
✓ Branch 13 taken 89 times.
✓ Branch 14 taken 18 times.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 22 times.
✓ Branch 17 taken 8 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 10 times.
✓ Branch 24 taken 13 times.
✓ Branch 25 taken 12 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✓ Branch 29 taken 6 times.
✓ Branch 30 taken 10 times.
✓ Branch 31 taken 51 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 12 times.
✓ Branch 34 taken 10 times.
✓ Branch 35 taken 8 times.
✓ Branch 36 taken 8 times.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 42 taken 2 times.
✓ Branch 43 taken 55 times.
✓ Branch 44 taken 3 times.
✓ Branch 45 taken 1 times.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
|
121239331 | switch (error) { |
| 2483 | 120167456 | case DB_SUCCESS: | |
| 2484 | 120167456 | return (0); | |
| 2485 | |||
| 2486 | 55 | case DB_INTERRUPTED: | |
| 2487 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 54 times.
|
55 | thd_set_kill_status(thd != nullptr ? thd : current_thd); |
| 2488 | 55 | return (HA_ERR_GENERIC); | |
| 2489 | |||
| 2490 | 1 | case DB_FOREIGN_EXCEED_MAX_CASCADE: | |
| 2491 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | ut_ad(thd); |
| 2492 | 1 | my_error(ER_FK_DEPTH_EXCEEDED, MYF(0), FK_MAX_CASCADE_DEL); | |
| 2493 | 1 | return (HA_ERR_FK_DEPTH_EXCEEDED); | |
| 2494 | |||
| 2495 | ✗ | case DB_CANT_CREATE_GEOMETRY_OBJECT: | |
| 2496 | ✗ | my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, MYF(0)); | |
| 2497 | ✗ | return (HA_ERR_NULL_IN_SPATIAL); | |
| 2498 | |||
| 2499 | 201 | case DB_ERROR: | |
| 2500 | default: | ||
| 2501 | 201 | return (HA_ERR_GENERIC); /* unspecified error */ | |
| 2502 | |||
| 2503 | 1070391 | case DB_DUPLICATE_KEY: | |
| 2504 | /* Be cautious with returning this error, since | ||
| 2505 | mysql could re-enter the storage layer to get | ||
| 2506 | duplicated key info, the operation requires a | ||
| 2507 | valid table handle and/or transaction information, | ||
| 2508 | which might not always be available in the error | ||
| 2509 | handling stage. */ | ||
| 2510 | 1070391 | return (HA_ERR_FOUND_DUPP_KEY); | |
| 2511 | |||
| 2512 | 4 | case DB_READ_ONLY: | |
| 2513 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (srv_force_recovery) { |
| 2514 | 4 | return (HA_ERR_INNODB_FORCED_RECOVERY); | |
| 2515 | } | ||
| 2516 | ✗ | return (HA_ERR_TABLE_READONLY); | |
| 2517 | |||
| 2518 | 4 | case DB_FOREIGN_DUPLICATE_KEY: | |
| 2519 | 4 | return (HA_ERR_FOREIGN_DUPLICATE_KEY); | |
| 2520 | |||
| 2521 | ✗ | case DB_MISSING_HISTORY: | |
| 2522 | ✗ | return (HA_ERR_TABLE_DEF_CHANGED); | |
| 2523 | |||
| 2524 | ✗ | case DB_RECORD_NOT_FOUND: | |
| 2525 | ✗ | return (HA_ERR_NO_ACTIVE_RECORD); | |
| 2526 | |||
| 2527 | 485 | case DB_FORCED_ABORT: | |
| 2528 | case DB_DEADLOCK: | ||
| 2529 | /* Since we rolled back the whole transaction, we must | ||
| 2530 | tell it also to MySQL so that MySQL knows to empty the | ||
| 2531 | cached binlog for this transaction */ | ||
| 2532 | |||
| 2533 |
1/2✓ Branch 0 taken 485 times.
✗ Branch 1 not taken.
|
485 | if (thd != nullptr) { |
| 2534 | 485 | thd_mark_transaction_to_rollback(thd, 1); | |
| 2535 | } | ||
| 2536 | |||
| 2537 | 485 | return (HA_ERR_LOCK_DEADLOCK); | |
| 2538 | |||
| 2539 | 427 | case DB_LOCK_WAIT_TIMEOUT: | |
| 2540 | /* Starting from 5.0.13, we let MySQL just roll back the | ||
| 2541 | latest SQL statement in a lock wait timeout. Previously, we | ||
| 2542 | rolled back the whole transaction. */ | ||
| 2543 | |||
| 2544 |
1/2✓ Branch 0 taken 427 times.
✗ Branch 1 not taken.
|
427 | if (thd) { |
| 2545 | 427 | thd_mark_transaction_to_rollback(thd, (int)row_rollback_on_timeout); | |
| 2546 | } | ||
| 2547 | |||
| 2548 | 428 | return (HA_ERR_LOCK_WAIT_TIMEOUT); | |
| 2549 | |||
| 2550 | 106 | case DB_NO_REFERENCED_ROW: | |
| 2551 | 106 | return (HA_ERR_NO_REFERENCED_ROW); | |
| 2552 | |||
| 2553 | 89 | case DB_ROW_IS_REFERENCED: | |
| 2554 | 89 | return (HA_ERR_ROW_IS_REFERENCED); | |
| 2555 | |||
| 2556 | 18 | case DB_NO_FK_ON_S_BASE_COL: | |
| 2557 | case DB_CANNOT_ADD_CONSTRAINT: | ||
| 2558 | case DB_CHILD_NO_INDEX: | ||
| 2559 | case DB_PARENT_NO_INDEX: | ||
| 2560 | 18 | return (HA_ERR_CANNOT_ADD_FOREIGN); | |
| 2561 | |||
| 2562 | 3 | case DB_CANNOT_DROP_CONSTRAINT: | |
| 2563 | |||
| 2564 | 3 | return (HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit | |
| 2565 | misleading, a new MySQL error | ||
| 2566 | code should be introduced */ | ||
| 2567 | |||
| 2568 | 22 | case DB_CORRUPTION: | |
| 2569 | 22 | return (HA_ERR_CRASHED); | |
| 2570 | |||
| 2571 | 8 | case DB_OUT_OF_FILE_SPACE: | |
| 2572 | 8 | return (HA_ERR_RECORD_FILE_FULL); | |
| 2573 | |||
| 2574 | ✗ | case DB_OUT_OF_DISK_SPACE: | |
| 2575 | ✗ | return (HA_ERR_DISK_FULL_NOWAIT); | |
| 2576 | |||
| 2577 | ✗ | case DB_TEMP_FILE_WRITE_FAIL: | |
| 2578 | ✗ | return (HA_ERR_TEMP_FILE_WRITE_FAILURE); | |
| 2579 | |||
| 2580 | ✗ | case DB_TABLE_IN_FK_CHECK: | |
| 2581 | ✗ | return (HA_ERR_TABLE_IN_FK_CHECK); | |
| 2582 | |||
| 2583 | ✗ | case DB_TABLE_IS_BEING_USED: | |
| 2584 | ✗ | return (HA_ERR_WRONG_COMMAND); | |
| 2585 | |||
| 2586 | 2 | case DB_TABLE_NOT_FOUND: | |
| 2587 | 2 | return (HA_ERR_NO_SUCH_TABLE); | |
| 2588 | |||
| 2589 | 10 | case DB_TABLESPACE_NOT_FOUND: | |
| 2590 | 10 | return (HA_ERR_TABLESPACE_MISSING); | |
| 2591 | |||
| 2592 | 13 | case DB_TOO_BIG_RECORD: { | |
| 2593 | /* If prefix is true then a 768-byte prefix is stored | ||
| 2594 | locally for BLOB fields. Refer to dict_table_get_format(). | ||
| 2595 | We limit max record size to 16k for 64k page size. */ | ||
| 2596 | 13 | bool prefix = !DICT_TF_HAS_ATOMIC_BLOBS(flags); | |
| 2597 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 11 times.
|
26 | my_printf_error( |
| 2598 | ER_TOO_BIG_ROWSIZE, | ||
| 2599 | "Row size too large (> %lu). Changing some columns" | ||
| 2600 | " to TEXT or BLOB %smay help. In current row" | ||
| 2601 | " format, BLOB prefix of %d bytes is stored inline.", | ||
| 2602 | MYF(0), | ||
| 2603 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | srv_page_size == UNIV_PAGE_SIZE_MAX |
| 2604 | ? REC_MAX_DATA_SIZE - 1 | ||
| 2605 | 13 | : page_get_free_space_of_empty(flags & DICT_TF_COMPACT) / 2, | |
| 2606 | prefix ? "or using ROW_FORMAT=DYNAMIC or" | ||
| 2607 | " ROW_FORMAT=COMPRESSED " | ||
| 2608 | : "", | ||
| 2609 | prefix ? DICT_MAX_FIXED_COL_LEN : 0); | ||
| 2610 | 13 | return (HA_ERR_TOO_BIG_ROW); | |
| 2611 | } | ||
| 2612 | |||
| 2613 | 12 | case DB_TOO_BIG_INDEX_COL: | |
| 2614 | 12 | my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0), | |
| 2615 | DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags)); | ||
| 2616 | 12 | return (HA_ERR_INDEX_COL_TOO_LONG); | |
| 2617 | |||
| 2618 | ✗ | case DB_NO_SAVEPOINT: | |
| 2619 | ✗ | return (HA_ERR_NO_SAVEPOINT); | |
| 2620 | |||
| 2621 | ✗ | case DB_LOCK_TABLE_FULL: | |
| 2622 | /* Since we rolled back the whole transaction, we must | ||
| 2623 | tell it also to MySQL so that MySQL knows to empty the | ||
| 2624 | cached binlog for this transaction */ | ||
| 2625 | |||
| 2626 | ✗ | if (thd) { | |
| 2627 | ✗ | thd_mark_transaction_to_rollback(thd, 1); | |
| 2628 | } | ||
| 2629 | |||
| 2630 | ✗ | return (HA_ERR_LOCK_TABLE_FULL); | |
| 2631 | |||
| 2632 | 3 | case DB_FTS_INVALID_DOCID: | |
| 2633 | 3 | return (HA_FTS_INVALID_DOCID); | |
| 2634 | 6 | case DB_FTS_EXCEED_RESULT_CACHE_LIMIT: | |
| 2635 | 6 | return (HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT); | |
| 2636 | 10 | case DB_TOO_MANY_CONCURRENT_TRXS: | |
| 2637 | 10 | return (HA_ERR_TOO_MANY_CONCURRENT_TRXS); | |
| 2638 | 51 | case DB_UNSUPPORTED: | |
| 2639 | 51 | return (HA_ERR_UNSUPPORTED); | |
| 2640 | ✗ | case DB_INDEX_CORRUPT: | |
| 2641 | ✗ | return (HA_ERR_INDEX_CORRUPT); | |
| 2642 | 12 | case DB_UNDO_RECORD_TOO_BIG: | |
| 2643 | 12 | return (HA_ERR_UNDO_REC_TOO_BIG); | |
| 2644 | 10 | case DB_OUT_OF_MEMORY: | |
| 2645 | 10 | return (HA_ERR_OUT_OF_MEM); | |
| 2646 | 8 | case DB_TABLESPACE_EXISTS: | |
| 2647 | 8 | return (HA_ERR_TABLESPACE_EXISTS); | |
| 2648 | 8 | case DB_TABLESPACE_DELETED: | |
| 2649 | 8 | return (HA_ERR_TABLESPACE_MISSING); | |
| 2650 | ✗ | case DB_IDENTIFIER_TOO_LONG: | |
| 2651 | ✗ | return (HA_ERR_INTERNAL_ERROR); | |
| 2652 | ✗ | case DB_TOO_LONG_PATH: | |
| 2653 | ✗ | return (HA_ERR_TOO_LONG_PATH); | |
| 2654 | 1 | case DB_TABLE_CORRUPT: | |
| 2655 | 1 | return (HA_ERR_TABLE_CORRUPT); | |
| 2656 | ✗ | case DB_FTS_TOO_MANY_WORDS_IN_PHRASE: | |
| 2657 | ✗ | return (HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE); | |
| 2658 | ✗ | case DB_WRONG_FILE_NAME: | |
| 2659 | ✗ | return (HA_ERR_WRONG_FILE_NAME); | |
| 2660 | 2 | case DB_COMPUTE_VALUE_FAILED: | |
| 2661 | 2 | return (HA_ERR_COMPUTE_FAILED); | |
| 2662 | 55 | case DB_LOCK_NOWAIT: | |
| 2663 | 55 | my_error(ER_LOCK_NOWAIT, MYF(0)); | |
| 2664 | 55 | return (HA_ERR_NO_WAIT_LOCK); | |
| 2665 | 3 | case DB_NO_SESSION_TEMP: | |
| 2666 | 3 | return (HA_ERR_NO_SESSION_TEMP); | |
| 2667 | 1 | case DB_BTREE_LEVEL_LIMIT_EXCEEDED: | |
| 2668 | 1 | return (HA_ERR_INTERNAL_ERROR); | |
| 2669 | ✗ | case DB_FTS_TOO_MANY_NESTED_EXP: | |
| 2670 | ✗ | return (HA_ERR_FTS_TOO_MANY_NESTED_EXP); | |
| 2671 | ✗ | case DB_IO_NO_PUNCH_HOLE: | |
| 2672 | case DB_IO_NO_PUNCH_HOLE_FS: | ||
| 2673 | case DB_IO_NO_PUNCH_HOLE_TABLESPACE: | ||
| 2674 | ✗ | return HA_ERR_UNSUPPORTED; | |
| 2675 | } | ||
| 2676 | } | ||
| 2677 | |||
| 2678 | /** Prints info of a THD object (== user session thread) to the given file. */ | ||
| 2679 | 623 | void innobase_mysql_print_thd( | |
| 2680 | FILE *f, /*!< in: output stream */ | ||
| 2681 | THD *thd, /*!< in: MySQL THD object */ | ||
| 2682 | uint max_query_len) /*!< in: max query length to print, or 0 to | ||
| 2683 | use the default max length */ | ||
| 2684 | { | ||
| 2685 | char buffer[1024]; | ||
| 2686 | |||
| 2687 |
2/4✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 623 times.
✗ Branch 3 not taken.
|
623 | fputs(thd_security_context(thd, buffer, sizeof buffer, max_query_len), f); |
| 2688 |
1/2✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
|
623 | putc('\n', f); |
| 2689 | 623 | } | |
| 2690 | |||
| 2691 | /** Get the error message format string. | ||
| 2692 | @return the format string or 0 if not found. */ | ||
| 2693 | 9020 | const char *innobase_get_err_msg(int error_code) /*!< in: MySQL error code */ | |
| 2694 | { | ||
| 2695 | 9020 | return (my_get_err_msg(error_code)); | |
| 2696 | } | ||
| 2697 | |||
| 2698 | /** Get the variable length bounds of the given character set. | ||
| 2699 | @param[in] cset Mysql charset-collation code | ||
| 2700 | @param[out] mbminlen Minimum length of a char (in bytes) | ||
| 2701 | @param[out] mbmaxlen Maximum length of a char (in bytes) */ | ||
| 2702 | 73890160 | void innobase_get_cset_width(ulint cset, ulint *mbminlen, ulint *mbmaxlen) { | |
| 2703 | CHARSET_INFO *cs; | ||
| 2704 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73885613 times.
|
73890160 | ut_ad(cset <= MAX_CHAR_COLL_NUM); |
| 2705 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73876757 times.
|
73885613 | ut_ad(mbminlen); |
| 2706 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73875138 times.
|
73876757 | ut_ad(mbmaxlen); |
| 2707 | |||
| 2708 | 73875138 | cs = all_charsets[cset]; | |
| 2709 |
2/2✓ Branch 0 taken 16272774 times.
✓ Branch 1 taken 57602364 times.
|
73875138 | if (cs) { |
| 2710 | 16272774 | *mbminlen = cs->mbminlen; | |
| 2711 | 16272774 | *mbmaxlen = cs->mbmaxlen; | |
| 2712 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16272766 times.
|
16272774 | ut_ad(*mbminlen < DATA_MBMAX); |
| 2713 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16272790 times.
|
16272766 | ut_ad(*mbmaxlen < DATA_MBMAX); |
| 2714 | } else { | ||
| 2715 | 57602364 | THD *thd = current_thd; | |
| 2716 | |||
| 2717 |
6/6✓ Branch 0 taken 50563844 times.
✓ Branch 1 taken 7038730 times.
✓ Branch 2 taken 495215 times.
✓ Branch 3 taken 50068734 times.
✓ Branch 4 taken 495215 times.
✓ Branch 5 taken 57107464 times.
|
57602574 | if (thd && thd_sql_command(thd) == SQLCOM_DROP_TABLE) { |
| 2718 | /* Fix bug#46256: allow tables to be dropped if the | ||
| 2719 | collation is not found, but issue a warning. */ | ||
| 2720 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 495215 times.
|
495215 | if (cset != 0) { |
| 2721 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_UNKNOWN_COLLATION); | |
| 2722 | } | ||
| 2723 | } else { | ||
| 2724 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57105299 times.
|
57107464 | ut_a(cset == 0); |
| 2725 | } | ||
| 2726 | |||
| 2727 | 57602262 | *mbminlen = *mbmaxlen = 0; | |
| 2728 | } | ||
| 2729 | 73875052 | } | |
| 2730 | |||
| 2731 | /********************************************************************** | ||
| 2732 | Check if the length of the identifier exceeds the maximum allowed. | ||
| 2733 | return true when length of identifier is too long. */ | ||
| 2734 | 292 | bool innobase_check_identifier_length( | |
| 2735 | const char *id) /* in: FK identifier to check excluding the | ||
| 2736 | database portion. */ | ||
| 2737 | { | ||
| 2738 | 292 | int well_formed_error = 0; | |
| 2739 | 292 | CHARSET_INFO *cs = system_charset_info; | |
| 2740 |
1/2✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
|
292 | DBUG_TRACE; |
| 2741 | |||
| 2742 |
1/2✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
|
292 | size_t len = cs->cset->well_formed_len(cs, id, id + strlen(id), NAME_CHAR_LEN, |
| 2743 | &well_formed_error); | ||
| 2744 | |||
| 2745 |
2/4✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 292 times.
|
292 | if (well_formed_error || len != strlen(id)) { |
| 2746 | ✗ | my_error(ER_TOO_LONG_IDENT, MYF(0), id); | |
| 2747 | ✗ | return true; | |
| 2748 | } | ||
| 2749 | 292 | return false; | |
| 2750 | 292 | } | |
| 2751 | #endif /* !UNIV_HOTBACKUP */ | ||
| 2752 | |||
| 2753 | /** Compares NUL-terminated UTF-8 strings case insensitively. | ||
| 2754 | @return 0 if a=b, <0 if a\<b, >1 if a>b */ | ||
| 2755 | 30101033 | int innobase_strcasecmp(const char *a, /*!< in: first string to compare */ | |
| 2756 | const char *b) /*!< in: second string to compare */ | ||
| 2757 | { | ||
| 2758 |
2/2✓ Branch 0 taken 1067377 times.
✓ Branch 1 taken 29033656 times.
|
30101033 | if (!a) { |
| 2759 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1067377 times.
|
1067377 | if (!b) { |
| 2760 | ✗ | return (0); | |
| 2761 | } else { | ||
| 2762 | 1067377 | return (-1); | |
| 2763 | } | ||
| 2764 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29033656 times.
|
29033656 | } else if (!b) { |
| 2765 | ✗ | return (1); | |
| 2766 | } | ||
| 2767 | |||
| 2768 | 29033656 | return (my_strcasecmp(system_charset_info, a, b)); | |
| 2769 | } | ||
| 2770 | |||
| 2771 | #ifndef UNIV_HOTBACKUP | ||
| 2772 | /** Compares NUL-terminated UTF-8 strings case insensitively. The | ||
| 2773 | second string contains wildcards. | ||
| 2774 | @return 0 if a match is found, 1 if not */ | ||
| 2775 | 23959 | static int innobase_wildcasecmp( | |
| 2776 | const char *a, /*!< in: string to compare */ | ||
| 2777 | const char *b) /*!< in: wildcard string to compare */ | ||
| 2778 | { | ||
| 2779 | 23959 | return (wild_case_compare(system_charset_info, a, b)); | |
| 2780 | } | ||
| 2781 | #endif /* !UNIV_HOTBACKUP */ | ||
| 2782 | |||
| 2783 | /** Strip dir name from a full path name and return only the file name | ||
| 2784 | @param[in] path_name full path name | ||
| 2785 | @return file name or "null" if no file name */ | ||
| 2786 | 141 | const char *innobase_basename(const char *path_name) { | |
| 2787 | 141 | const char *name = base_name(path_name); | |
| 2788 | |||
| 2789 |
1/2✓ Branch 0 taken 141 times.
✗ Branch 1 not taken.
|
141 | return ((name) ? name : "null"); |
| 2790 | } | ||
| 2791 | |||
| 2792 | #ifndef UNIV_HOTBACKUP | ||
| 2793 | |||
| 2794 | /** Makes all characters in a NUL-terminated UTF-8 string lower case. */ | ||
| 2795 | 1104573 | void innobase_casedn_str(char *a) /*!< in/out: string to put in lower case */ | |
| 2796 | { | ||
| 2797 | 1104573 | my_casedn_str(system_charset_info, a); | |
| 2798 | 1104589 | } | |
| 2799 | |||
| 2800 | /** Makes all characters in a NUL-terminated UTF-8 path string lower case. */ | ||
| 2801 | 30 | void innobase_casedn_path(char *a) /*!< in/out: string to put in lower case */ | |
| 2802 | { | ||
| 2803 | 30 | my_casedn_str(&my_charset_filename, a); | |
| 2804 | 30 | } | |
| 2805 | |||
| 2806 | /** Determines the connection character set. | ||
| 2807 | @return connection character set */ | ||
| 2808 | 59 | const CHARSET_INFO *innobase_get_charset( | |
| 2809 | THD *mysql_thd) /*!< in: MySQL thread handle */ | ||
| 2810 | { | ||
| 2811 | 59 | return (thd_charset(mysql_thd)); | |
| 2812 | } | ||
| 2813 | |||
| 2814 | /** Determines the current SQL statement. | ||
| 2815 | Thread unsafe, can only be called from the thread owning the THD. | ||
| 2816 | @param[in] thd MySQL thread handle | ||
| 2817 | @param[out] length Length of the SQL statement | ||
| 2818 | @return SQL statement string */ | ||
| 2819 | 347994 | const char *innobase_get_stmt_unsafe(THD *thd, size_t *length) { | |
| 2820 | LEX_CSTRING stmt; | ||
| 2821 | |||
| 2822 |
1/2✓ Branch 0 taken 347994 times.
✗ Branch 1 not taken.
|
347994 | stmt = thd_query_unsafe(thd); |
| 2823 | 347994 | *length = stmt.length; | |
| 2824 | 347994 | return (stmt.str); | |
| 2825 | } | ||
| 2826 | |||
| 2827 | /** Determines the current SQL statement. | ||
| 2828 | Thread safe, can be called from any thread as the string is copied | ||
| 2829 | into the provided buffer. | ||
| 2830 | @param[in] thd MySQL thread handle | ||
| 2831 | @param[out] buf Buffer containing SQL statement | ||
| 2832 | @param[in] buflen Length of provided buffer | ||
| 2833 | @return Length of the SQL statement */ | ||
| 2834 | 74 | size_t innobase_get_stmt_safe(THD *thd, char *buf, size_t buflen) { | |
| 2835 | 74 | return (thd_query_safe(thd, buf, buflen)); | |
| 2836 | } | ||
| 2837 | |||
| 2838 | /** Get the current setting of the table_def_size global parameter. We do | ||
| 2839 | a dirty read because for one there is no synchronization object and | ||
| 2840 | secondly there is little harm in doing so even if we get a torn read. | ||
| 2841 | @return value of table_def_size */ | ||
| 2842 | 206064 | ulint innobase_get_table_cache_size(void) { return (table_def_size); } | |
| 2843 | |||
| 2844 | /** Get the current setting of the lower_case_table_names global parameter from | ||
| 2845 | mysqld.cc. We do a dirty read because for one there is no synchronization | ||
| 2846 | object and secondly there is little harm in doing so even if we get a torn | ||
| 2847 | read. | ||
| 2848 | @return value of lower_case_table_names */ | ||
| 2849 | 29845993 | ulint innobase_get_lower_case_table_names(void) { | |
| 2850 | 29845993 | return (lower_case_table_names); | |
| 2851 | } | ||
| 2852 | |||
| 2853 | 19200 | char *innobase_mysql_tmpdir() { return (mysql_tmpdir); } | |
| 2854 | |||
| 2855 | 67382 | os_fd_t innobase_mysql_tmpfile(const char *path) { | |
| 2856 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67382 times.
|
67382 | DBUG_EXECUTE_IF("innobase_tmpfile_creation_failure", return (-1);); |
| 2857 | |||
| 2858 | #ifdef WITH_WSREP | ||
| 2859 | 67382 | os_event_wait(srv_allow_writes_event); | |
| 2860 | #endif /* WITH_WSREP */ | ||
| 2861 | |||
| 2862 | auto fd = | ||
| 2863 |
2/2✓ Branch 0 taken 9645 times.
✓ Branch 1 taken 57743 times.
|
67388 | (path == nullptr) ? mysql_tmpfile("ib") : mysql_tmpfile_path(path, "ib"); |
| 2864 | |||
| 2865 | 67388 | os_fd_t fd2{OS_FD_CLOSED}; | |
| 2866 | |||
| 2867 |
2/2✓ Branch 0 taken 67387 times.
✓ Branch 1 taken 1 times.
|
67388 | if (fd >= 0) { |
| 2868 | /* Copy the file descriptor, so that the additional resources | ||
| 2869 | allocated by create_temp_file() can be freed by invoking | ||
| 2870 | my_close(). | ||
| 2871 | |||
| 2872 | Because the file descriptor returned by this function | ||
| 2873 | will be passed to fdopen(), it will be closed by invoking | ||
| 2874 | fclose(), which in turn will invoke close() instead of | ||
| 2875 | my_close(). */ | ||
| 2876 | |||
| 2877 | #ifdef _WIN32 | ||
| 2878 | /* Note that on Windows, the integer returned by mysql_tmpfile | ||
| 2879 | has no relation to C runtime file descriptor. Here, we need | ||
| 2880 | to call my_get_osfhandle to get the HANDLE and then convert it | ||
| 2881 | to C runtime filedescriptor. */ | ||
| 2882 | { | ||
| 2883 | HANDLE hDup; | ||
| 2884 | |||
| 2885 | auto hFile = my_get_osfhandle(fd); | ||
| 2886 | |||
| 2887 | auto bOK = | ||
| 2888 | DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(), | ||
| 2889 | &hDup, 0, false, DUPLICATE_SAME_ACCESS); | ||
| 2890 | if (bOK) { | ||
| 2891 | fd2 = _open_osfhandle((intptr_t)hDup, 0); | ||
| 2892 | } else { | ||
| 2893 | my_osmaperr(GetLastError()); | ||
| 2894 | fd2 = OS_FD_CLOSED; | ||
| 2895 | } | ||
| 2896 | } | ||
| 2897 | #else | ||
| 2898 | 67387 | fd2 = dup(fd); | |
| 2899 | #endif | ||
| 2900 | |||
| 2901 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67386 times.
|
67386 | if (fd2 < 0) { |
| 2902 | char errbuf[MYSYS_STRERROR_SIZE]; | ||
| 2903 | |||
| 2904 | ✗ | DBUG_PRINT("error", ("Got error %d on dup", fd2)); | |
| 2905 | |||
| 2906 | ✗ | set_my_errno(errno); | |
| 2907 | |||
| 2908 | ✗ | my_error(EE_OUT_OF_FILERESOURCES, MYF(0), "ib*", my_errno(), | |
| 2909 | my_strerror(errbuf, sizeof(errbuf), my_errno())); | ||
| 2910 | } | ||
| 2911 | |||
| 2912 | 67386 | my_close(fd, MYF(MY_WME)); | |
| 2913 | } | ||
| 2914 | |||
| 2915 | 67388 | return fd2; | |
| 2916 | } | ||
| 2917 | |||
| 2918 | /** Wrapper around MySQL's copy_and_convert function. | ||
| 2919 | @return number of bytes copied to 'to' */ | ||
| 2920 | 272 | static ulint innobase_convert_string( | |
| 2921 | void *to, /*!< out: converted string */ | ||
| 2922 | ulint to_length, /*!< in: number of bytes reserved | ||
| 2923 | for the converted string */ | ||
| 2924 | CHARSET_INFO *to_cs, /*!< in: character set to convert to */ | ||
| 2925 | const void *from, /*!< in: string to convert */ | ||
| 2926 | ulint from_length, /*!< in: number of bytes to convert */ | ||
| 2927 | CHARSET_INFO *from_cs, /*!< in: character set to convert | ||
| 2928 | from */ | ||
| 2929 | uint *errors) /*!< out: number of errors encountered | ||
| 2930 | during the conversion */ | ||
| 2931 | { | ||
| 2932 | 272 | return (copy_and_convert((char *)to, (uint32)to_length, to_cs, | |
| 2933 | (const char *)from, (uint32)from_length, from_cs, | ||
| 2934 | 272 | errors)); | |
| 2935 | } | ||
| 2936 | |||
| 2937 | /** Formats the raw data in "data" (in InnoDB on-disk format) that is of | ||
| 2938 | type DATA_(CHAR|VARCHAR|MYSQL|VARMYSQL) using "charset_coll" and writes | ||
| 2939 | the result to "buf". The result is converted to "system_charset_info". | ||
| 2940 | Not more than "buf_size" bytes are written to "buf". | ||
| 2941 | The result is always NUL-terminated (provided buf_size > 0) and the | ||
| 2942 | number of bytes that were written to "buf" is returned (including the | ||
| 2943 | terminating NUL). | ||
| 2944 | @return number of bytes that were written */ | ||
| 2945 | 272 | ulint innobase_raw_format(const char *data, /*!< in: raw data */ | |
| 2946 | ulint data_len, /*!< in: raw data length | ||
| 2947 | in bytes */ | ||
| 2948 | ulint charset_coll, /*!< in: charset collation */ | ||
| 2949 | char *buf, /*!< out: output buffer */ | ||
| 2950 | ulint buf_size) /*!< in: output buffer size | ||
| 2951 | in bytes */ | ||
| 2952 | { | ||
| 2953 | /* XXX we use a hard limit instead of allocating | ||
| 2954 | but_size bytes from the heap */ | ||
| 2955 | CHARSET_INFO *data_cs; | ||
| 2956 | char buf_tmp[8192]; | ||
| 2957 | ulint buf_tmp_used; | ||
| 2958 | uint num_errors; | ||
| 2959 | |||
| 2960 | 272 | data_cs = all_charsets[charset_coll]; | |
| 2961 | |||
| 2962 | buf_tmp_used = | ||
| 2963 |
1/2✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
|
272 | innobase_convert_string(buf_tmp, sizeof(buf_tmp), system_charset_info, |
| 2964 | data, data_len, data_cs, &num_errors); | ||
| 2965 | |||
| 2966 | 544 | return (ut_str_sql_format(buf_tmp, buf_tmp_used, buf, buf_size)); | |
| 2967 | } | ||
| 2968 | |||
| 2969 | #endif /* !UNIV_HOTBACKUP */ | ||
| 2970 | |||
| 2971 | /** Check if the string is "empty" or "none". | ||
| 2972 | @param[in] algorithm Compression algorithm to check | ||
| 2973 | @return true if no algorithm requested */ | ||
| 2974 | 232097 | bool Compression::is_none(const char *algorithm) { | |
| 2975 | /* NULL is the same as NONE */ | ||
| 2976 |
5/6✓ Branch 0 taken 1660 times.
✓ Branch 1 taken 230437 times.
✓ Branch 2 taken 1660 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 231274 times.
✓ Branch 5 taken 823 times.
|
233757 | if (algorithm == nullptr || *algorithm == 0 || |
| 2977 |
2/2✓ Branch 0 taken 837 times.
✓ Branch 1 taken 823 times.
|
1660 | innobase_strcasecmp(algorithm, "none") == 0) { |
| 2978 | 231274 | return (true); | |
| 2979 | } | ||
| 2980 | |||
| 2981 | 823 | return (false); | |
| 2982 | } | ||
| 2983 | |||
| 2984 | /** Check wether the compression algorithm is supported. | ||
| 2985 | @param[in] algorithm Compression algorithm to check | ||
| 2986 | @param[out] compression The type that algorithm maps to | ||
| 2987 | @return DB_SUCCESS or error code */ | ||
| 2988 | 231558 | dberr_t Compression::check(const char *algorithm, Compression *compression) { | |
| 2989 |
2/2✓ Branch 0 taken 230739 times.
✓ Branch 1 taken 819 times.
|
231558 | if (is_none(algorithm)) { |
| 2990 | 230739 | compression->m_type = NONE; | |
| 2991 | |||
| 2992 |
2/2✓ Branch 0 taken 271 times.
✓ Branch 1 taken 548 times.
|
819 | } else if (innobase_strcasecmp(algorithm, "zlib") == 0) { |
| 2993 | 271 | compression->m_type = ZLIB; | |
| 2994 | |||
| 2995 |
2/2✓ Branch 0 taken 540 times.
✓ Branch 1 taken 8 times.
|
548 | } else if (innobase_strcasecmp(algorithm, "lz4") == 0) { |
| 2996 | 540 | compression->m_type = LZ4; | |
| 2997 | |||
| 2998 | } else { | ||
| 2999 | 8 | return (DB_UNSUPPORTED); | |
| 3000 | } | ||
| 3001 | |||
| 3002 | 231550 | return (DB_SUCCESS); | |
| 3003 | } | ||
| 3004 | |||
| 3005 | /** Validate the algorithm string. | ||
| 3006 | @param[in] algorithm Compression algorithm to check | ||
| 3007 | @return DB_SUCCESS or error code */ | ||
| 3008 | 230623 | dberr_t Compression::validate(const char *algorithm) { | |
| 3009 | 230623 | Compression compression; | |
| 3010 | |||
| 3011 |
1/2✓ Branch 0 taken 230623 times.
✗ Branch 1 not taken.
|
461246 | return (check(algorithm, &compression)); |
| 3012 | } | ||
| 3013 | |||
| 3014 | 580 | bool Compression::validate(const Compression::Type type) { | |
| 3015 | 580 | bool ret = true; | |
| 3016 | |||
| 3017 |
1/2✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
|
580 | switch (type) { |
| 3018 | 580 | case NONE: | |
| 3019 | case ZLIB: | ||
| 3020 | case LZ4: | ||
| 3021 | 580 | break; | |
| 3022 | ✗ | default: | |
| 3023 | ✗ | ret = false; | |
| 3024 | ✗ | break; | |
| 3025 | } | ||
| 3026 | |||
| 3027 | 580 | return ret; | |
| 3028 | } | ||
| 3029 | |||
| 3030 | #ifndef UNIV_HOTBACKUP | ||
| 3031 | 1597041 | bool Encryption::is_empty(const char *algorithm) noexcept { | |
| 3032 | /* nullptr is the same as empty */ | ||
| 3033 | 1597041 | return algorithm == nullptr; | |
| 3034 | } | ||
| 3035 | |||
| 3036 | 1597042 | bool Encryption::is_none(const char *algorithm) noexcept { | |
| 3037 |
2/2✓ Branch 0 taken 1285305 times.
✓ Branch 1 taken 311736 times.
|
2882348 | return Encryption::is_empty(algorithm) || |
| 3038 |
2/2✓ Branch 0 taken 1264884 times.
✓ Branch 1 taken 20422 times.
|
2882347 | innobase_strcasecmp(algorithm, "n") == 0; |
| 3039 | } | ||
| 3040 | |||
| 3041 | /** Check if the string is "y" or "Y". | ||
| 3042 | @param[in] algorithm Encryption algorithm to check | ||
| 3043 | @return true if no algorithm requested */ | ||
| 3044 | 1521302 | bool Encryption::is_master_key_encryption(const char *algorithm) noexcept { | |
| 3045 | 1521302 | return innobase_strcasecmp(algorithm, "y") == 0; | |
| 3046 | } | ||
| 3047 | |||
| 3048 | /** Check if the NO algorithm was explicitly specified. | ||
| 3049 | @param[in] algorithm Encryption algorithm to check | ||
| 3050 | @return true if no algorithm explicitly requested */ | ||
| 3051 | 1507607 | bool Encryption::none_explicitly_specified(bool explicit_encryption, | |
| 3052 | const char *algorithm) noexcept { | ||
| 3053 |
2/2✓ Branch 0 taken 269304 times.
✓ Branch 1 taken 1238303 times.
|
1507607 | if (explicit_encryption) { |
| 3054 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 269304 times.
|
269304 | ut_ad(algorithm != nullptr); |
| 3055 | 269304 | return innobase_strcasecmp(algorithm, "n") == 0; | |
| 3056 | } | ||
| 3057 | 1238303 | return false; | |
| 3058 | } | ||
| 3059 | |||
| 3060 | 1548213 | bool Encryption::is_keyring(const char *algoritm) noexcept { | |
| 3061 |
3/4✓ Branch 0 taken 480852 times.
✓ Branch 1 taken 1067361 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 480852 times.
|
1548213 | return (algoritm != nullptr && innobase_strcasecmp(algoritm, "keyring") == 0); |
| 3062 | } | ||
| 3063 | |||
| 3064 | 910306 | bool Encryption::is_online_encryption_on() noexcept { | |
| 3065 | 910306 | return srv_default_table_encryption == DEFAULT_TABLE_ENC_ONLINE_TO_KEYRING; | |
| 3066 | } | ||
| 3067 | |||
| 3068 | // This for now excludes MK encryption ... | ||
| 3069 | 637316 | bool Encryption::should_be_keyring_encrypted(bool explicit_encryption, | |
| 3070 | const char *algorithm) noexcept { | ||
| 3071 |
3/4✓ Branch 0 taken 577935 times.
✓ Branch 1 taken 59381 times.
✓ Branch 2 taken 577935 times.
✗ Branch 3 not taken.
|
1793186 | return !none_explicitly_specified(explicit_encryption, algorithm) && |
| 3072 | 577935 | (is_keyring(algorithm) || | |
| 3073 |
4/4✓ Branch 0 taken 572186 times.
✓ Branch 1 taken 5749 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 572181 times.
|
1150121 | (!Encryption::is_master_key_encryption(algorithm) && |
| 3074 | 1209502 | is_online_encryption_on())); | |
| 3075 | } | ||
| 3076 | |||
| 3077 | 278763 | dberr_t Encryption::set_algorithm(const char *option, | |
| 3078 | Encryption *encryption) noexcept { | ||
| 3079 |
2/2✓ Branch 0 taken 266939 times.
✓ Branch 1 taken 11826 times.
|
278763 | if (is_none(option)) { |
| 3080 | 266939 | encryption->m_type = NONE; | |
| 3081 | |||
| 3082 |
2/2✓ Branch 0 taken 11750 times.
✓ Branch 1 taken 76 times.
|
11826 | } else if (innobase_strcasecmp(option, "y") == 0) { |
| 3083 | 11750 | encryption->m_type = AES; | |
| 3084 | |||
| 3085 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
|
76 | } else if (innobase_strcasecmp(option, "KEYRING") == 0) { |
| 3086 | #ifdef WITH_WSREP | ||
| 3087 | ✗ | return (DB_UNSUPPORTED); | |
| 3088 | #else | ||
| 3089 | encryption->m_type = KEYRING; | ||
| 3090 | #endif | ||
| 3091 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
|
76 | } else if (innobase_strcasecmp(option, "ONLINE_TO_KEYRING") == 0) { |
| 3092 | #ifdef WITH_WSREP | ||
| 3093 | ✗ | return (DB_UNSUPPORTED); | |
| 3094 | #else | ||
| 3095 | encryption->m_type = KEYRING; | ||
| 3096 | #endif | ||
| 3097 | } else { | ||
| 3098 | 76 | return (DB_UNSUPPORTED); | |
| 3099 | } | ||
| 3100 | |||
| 3101 | 278689 | return (DB_SUCCESS); | |
| 3102 | } | ||
| 3103 | |||
| 3104 | 277386 | dberr_t Encryption::validate(const char *option) noexcept { | |
| 3105 | 277386 | Encryption encryption; | |
| 3106 | |||
| 3107 | 277388 | return (encryption.set_algorithm(option, &encryption)); | |
| 3108 | 277389 | } | |
| 3109 | |||
| 3110 | /** Check for supported ENCRYPT := (Y | N) supported values | ||
| 3111 | @param[in] option Encryption option | ||
| 3112 | @return DB_SUCCESS or DB_UNSUPPORTED */ | ||
| 3113 | 1376 | dberr_t Encryption::validate_for_tablespace(const char *option) noexcept { | |
| 3114 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1376 times.
|
1376 | if (innobase_strcasecmp(option, "KEYRING") == 0) { |
| 3115 | ✗ | return DB_UNSUPPORTED; | |
| 3116 | } | ||
| 3117 | |||
| 3118 | 1376 | Encryption encryption; | |
| 3119 | |||
| 3120 | 1376 | return (encryption.set_algorithm(option, &encryption)); | |
| 3121 | 1376 | } | |
| 3122 | /** Compute the next autoinc value. | ||
| 3123 | |||
| 3124 | For MySQL replication the autoincrement values can be partitioned among | ||
| 3125 | the nodes. The offset is the start or origin of the autoincrement value | ||
| 3126 | for a particular node. For n nodes the increment will be n and the offset | ||
| 3127 | will be in the interval [1, n]. The formula tries to allocate the next | ||
| 3128 | value for a particular node. | ||
| 3129 | |||
| 3130 | Note: This function is also called with increment set to the number of | ||
| 3131 | values we want to reserve for multi-value inserts e.g., | ||
| 3132 | |||
| 3133 | INSERT INTO T VALUES(), (), (); | ||
| 3134 | |||
| 3135 | innobase_next_autoinc() will be called with increment set to 3 where | ||
| 3136 | autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for | ||
| 3137 | the multi-value INSERT above. | ||
| 3138 | @return the next value */ | ||
| 3139 | 9234449 | ulonglong innobase_next_autoinc( | |
| 3140 | ulonglong current, /*!< in: Current value */ | ||
| 3141 | ulonglong need, /*!< in: count of values needed */ | ||
| 3142 | ulonglong step, /*!< in: AUTOINC increment step */ | ||
| 3143 | ulonglong offset, /*!< in: AUTOINC offset */ | ||
| 3144 | ulonglong max_value) /*!< in: max value for type */ | ||
| 3145 | { | ||
| 3146 | ulonglong next_value; | ||
| 3147 | 9234449 | ulonglong block = need * step; | |
| 3148 | |||
| 3149 | /* Should never be 0. */ | ||
| 3150 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234486 times.
|
9234449 | ut_a(need > 0); |
| 3151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234535 times.
|
9234486 | ut_a(block > 0); |
| 3152 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 9234521 times.
|
9234535 | ut_a(max_value > 0); |
| 3153 | |||
| 3154 | /* According to MySQL documentation, if the offset is greater than | ||
| 3155 | the step then the offset is ignored. */ | ||
| 3156 |
2/2✓ Branch 0 taken 10990 times.
✓ Branch 1 taken 9223531 times.
|
9234521 | if (offset > block) { |
| 3157 | 10990 | offset = 0; | |
| 3158 | } | ||
| 3159 | |||
| 3160 | /* Check for overflow. Current can be > max_value if the value is | ||
| 3161 | in reality a negative value.The visual studio compilers converts | ||
| 3162 | large double values automatically into unsigned long long datatype | ||
| 3163 | maximum value */ | ||
| 3164 | |||
| 3165 |
4/6✓ Branch 0 taken 9234531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9234540 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9234451 times.
✓ Branch 5 taken 89 times.
|
9234521 | if (block >= max_value || offset > max_value || current >= max_value || |
| 3166 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 9234426 times.
|
9234451 | max_value - offset <= offset) { |
| 3167 | 95 | next_value = max_value; | |
| 3168 | } else { | ||
| 3169 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 9234436 times.
|
9234426 | ut_a(max_value > current); |
| 3170 | |||
| 3171 | 9234436 | ulonglong free = max_value - current; | |
| 3172 | |||
| 3173 |
4/4✓ Branch 0 taken 9234423 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 9234419 times.
|
9234436 | if (free < offset || free - offset <= block) { |
| 3174 | 17 | next_value = max_value; | |
| 3175 | } else { | ||
| 3176 | 9234419 | next_value = 0; | |
| 3177 | } | ||
| 3178 | } | ||
| 3179 | |||
| 3180 |
2/2✓ Branch 0 taken 9234405 times.
✓ Branch 1 taken 126 times.
|
9234531 | if (next_value == 0) { |
| 3181 | ulonglong next; | ||
| 3182 | |||
| 3183 |
2/2✓ Branch 0 taken 9185656 times.
✓ Branch 1 taken 48749 times.
|
9234405 | if (current > offset) { |
| 3184 | 9185656 | next = (current - offset) / step; | |
| 3185 | } else { | ||
| 3186 | 48749 | next = (offset - current) / step; | |
| 3187 | } | ||
| 3188 | |||
| 3189 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234413 times.
|
9234405 | ut_a(max_value > next); |
| 3190 | 9234413 | next_value = next * step; | |
| 3191 | /* Check for multiplication overflow. */ | ||
| 3192 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234440 times.
|
9234413 | ut_a(next_value >= next); |
| 3193 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9234428 times.
|
9234440 | ut_a(max_value > next_value); |
| 3194 | |||
| 3195 | /* Check for overflow */ | ||
| 3196 |
1/2✓ Branch 0 taken 9234428 times.
✗ Branch 1 not taken.
|
9234428 | if (max_value - next_value >= block) { |
| 3197 | 9234428 | next_value += block; | |
| 3198 | |||
| 3199 |
1/2✓ Branch 0 taken 9234454 times.
✗ Branch 1 not taken.
|
9234428 | if (max_value - next_value >= offset) { |
| 3200 | 9234454 | next_value += offset; | |
| 3201 | } else { | ||
| 3202 | ✗ | next_value = max_value; | |
| 3203 | } | ||
| 3204 | } else { | ||
| 3205 | ✗ | next_value = max_value; | |
| 3206 | } | ||
| 3207 | } | ||
| 3208 | |||
| 3209 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234564 times.
|
9234554 | ut_a(next_value != 0); |
| 3210 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9234556 times.
|
9234564 | ut_a(next_value <= max_value); |
| 3211 | |||
| 3212 | 9234556 | return (next_value); | |
| 3213 | } | ||
| 3214 | |||
| 3215 | /** | ||
| 3216 | Check whether given connection should log stats for slow query log InnoDB | ||
| 3217 | extensions. | ||
| 3218 | |||
| 3219 | @param[in] thd connection handle | ||
| 3220 | @return whether stats for slow query log InnoDB extensions should be logged | ||
| 3221 | */ | ||
| 3222 | 2503566187 | static bool innobase_slow_log_verbose(THD *thd) noexcept { | |
| 3223 |
4/4✓ Branch 0 taken 2096953141 times.
✓ Branch 1 taken 390288043 times.
✓ Branch 2 taken 152690 times.
✓ Branch 3 taken 2096807714 times.
|
4584205600 | return thd && thd_opt_slow_log() && |
| 3224 |
2/2✓ Branch 0 taken 2487245196 times.
✓ Branch 1 taken 16320991 times.
|
7087767775 | unlikely(thd_log_slow_verbosity(thd) & (1ULL << SLOG_V_INNODB)) && |
| 3225 |
2/2✓ Branch 0 taken 146822 times.
✓ Branch 1 taken 5868 times.
|
2503722128 | !thd_is_background_thread(thd); |
| 3226 | } | ||
| 3227 | |||
| 3228 | /** Initializes some fields in an InnoDB transaction object. */ | ||
| 3229 | 1316788242 | static void innobase_trx_init( | |
| 3230 | THD *thd, /*!< in: user thread handle */ | ||
| 3231 | trx_t *trx) /*!< in/out: InnoDB transaction handle */ | ||
| 3232 | { | ||
| 3233 |
1/2✓ Branch 0 taken 1316801663 times.
✗ Branch 1 not taken.
|
1316788242 | DBUG_TRACE; |
| 3234 |
2/4✓ Branch 0 taken 1316801623 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1316801623 times.
|
1316801663 | assert(EQ_CURRENT_THD(thd)); |
| 3235 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1316801623 times.
|
1316801623 | assert(thd == trx->mysql_thd); |
| 3236 | |||
| 3237 |
1/2✓ Branch 0 taken 1316800546 times.
✗ Branch 1 not taken.
|
1316801623 | trx->check_foreigns = !thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS); |
| 3238 | |||
| 3239 | 1316799592 | trx->check_unique_secondary = | |
| 3240 |
1/2✓ Branch 0 taken 1316799592 times.
✗ Branch 1 not taken.
|
1316800546 | !thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS); |
| 3241 | |||
| 3242 | 1316799592 | trx->stats.set(innobase_slow_log_verbose(thd)); | |
| 3243 | 1316795190 | } | |
| 3244 | |||
| 3245 | /** Allocates an InnoDB transaction for a MySQL handler object for DML. | ||
| 3246 | @return InnoDB transaction handle */ | ||
| 3247 | 15667562 | trx_t *innobase_trx_allocate(THD *thd) /*!< in: user thread handle */ | |
| 3248 | { | ||
| 3249 | trx_t *trx; | ||
| 3250 | |||
| 3251 |
1/2✓ Branch 0 taken 15667587 times.
✗ Branch 1 not taken.
|
15667562 | DBUG_TRACE; |
| 3252 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15667587 times.
|
15667587 | assert(thd != nullptr); |
| 3253 |
2/4✓ Branch 0 taken 15667589 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15667589 times.
|
15667587 | assert(EQ_CURRENT_THD(thd)); |
| 3254 | |||
| 3255 | 15667589 | MONITOR_ATOMIC_INC(MONITOR_TRX_ALLOCATIONS); | |
| 3256 |
1/2✓ Branch 0 taken 15667593 times.
✗ Branch 1 not taken.
|
15667572 | trx = trx_allocate_for_mysql(); |
| 3257 | |||
| 3258 |
1/2✓ Branch 0 taken 15667593 times.
✗ Branch 1 not taken.
|
15667593 | rw_lock_s_lock(&purge_sys->latch, UT_LOCATION_HERE); |
| 3259 | |||
| 3260 |
3/4✓ Branch 0 taken 15667591 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14781 times.
✓ Branch 3 taken 15652812 times.
|
15667593 | if (purge_sys->thds.find(thd) != purge_sys->thds.end()) { |
| 3261 | 14781 | trx->purge_sys_trx = true; | |
| 3262 | } | ||
| 3263 | |||
| 3264 |
1/2✓ Branch 0 taken 15667593 times.
✗ Branch 1 not taken.
|
15667593 | rw_lock_s_unlock(&purge_sys->latch); |
| 3265 | |||
| 3266 | 15667593 | trx->mysql_thd = thd; | |
| 3267 | |||
| 3268 |
1/2✓ Branch 0 taken 15667593 times.
✗ Branch 1 not taken.
|
15667593 | innobase_trx_init(thd, trx); |
| 3269 | |||
| 3270 | 15667592 | return trx; | |
| 3271 | 15667593 | } | |
| 3272 | |||
| 3273 | /** Gets the InnoDB transaction handle for a MySQL handler object, creates | ||
| 3274 | an InnoDB transaction struct if the corresponding MySQL thread struct still | ||
| 3275 | lacks one. | ||
| 3276 | @return InnoDB transaction handle */ | ||
| 3277 | 1316791124 | trx_t *check_trx_exists(THD *thd) /*!< in: user thread handle */ | |
| 3278 | { | ||
| 3279 | /* We request to stop master thread in srv_shutdown, which is invoked | ||
| 3280 | after DD has been shut down. Since that point of time, we must not need | ||
| 3281 | transaction objects for any reasons. */ | ||
| 3282 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 1316789871 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1316787766 times.
|
2633580995 | ut_ad(srv_shutdown_state_matches([](auto state) { |
| 3283 | return state < SRV_SHUTDOWN_MASTER_STOP || | ||
| 3284 | state == SRV_SHUTDOWN_EXIT_THREADS; | ||
| 3285 | })); | ||
| 3286 | |||
| 3287 | 1316787766 | trx_t *&trx = thd_to_trx(thd); | |
| 3288 | |||
| 3289 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1316789586 times.
|
1316789348 | ut_ad(EQ_CURRENT_THD(thd)); |
| 3290 | |||
| 3291 |
2/2✓ Branch 0 taken 15667240 times.
✓ Branch 1 taken 1301122346 times.
|
1316789586 | if (trx == nullptr) { |
| 3292 | 15667240 | trx = innobase_trx_allocate(thd); | |
| 3293 | |||
| 3294 | /* User trx can be forced to rollback, | ||
| 3295 | so we unset the disable flag. */ | ||
| 3296 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15667249 times.
|
15667248 | ut_ad(trx->in_innodb & TRX_FORCE_ROLLBACK_DISABLE); |
| 3297 | |||
| 3298 | 15667249 | trx->in_innodb &= TRX_FORCE_ROLLBACK_MASK; | |
| 3299 | |||
| 3300 | } else { | ||
| 3301 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1301121470 times.
|
1301122346 | ut_a(trx->magic_n == TRX_MAGIC_N); |
| 3302 | |||
| 3303 | 1301121470 | innobase_trx_init(thd, trx); | |
| 3304 | } | ||
| 3305 | |||
| 3306 | 1316801134 | return (trx); | |
| 3307 | } | ||
| 3308 | |||
| 3309 | /** Get the transaction of the current connection handle, if either exists. | ||
| 3310 | @return transaction of the current connection handle, or NULL. */ | ||
| 3311 | ✗ | trx_t *innobase_get_trx(void) { | |
| 3312 | ✗ | THD *const thd = current_thd; | |
| 3313 | ✗ | if (UNIV_UNLIKELY(!thd)) return (nullptr); | |
| 3314 | |||
| 3315 | ✗ | return (thd_to_trx(thd)); | |
| 3316 | } | ||
| 3317 | |||
| 3318 | /** Get the transaction of the current connection handle if slow query log | ||
| 3319 | InnoDB extended statistics should be collected. | ||
| 3320 | @return transaction object if statistics should be collected, or NULL. */ | ||
| 3321 | 1186785948 | trx_t *innobase_get_trx_for_slow_log(void) noexcept { | |
| 3322 | 1186785948 | THD *thd = current_thd; | |
| 3323 |
2/2✓ Branch 0 taken 1186749191 times.
✓ Branch 1 taken 43810 times.
|
1186791614 | if (UNIV_LIKELY(!innobase_slow_log_verbose(thd))) return (nullptr); |
| 3324 | 43810 | trx_t *trx = thd_to_trx(thd); | |
| 3325 |
6/6✓ Branch 0 taken 41975 times.
✓ Branch 1 taken 1835 times.
✓ Branch 2 taken 41877 times.
✓ Branch 3 taken 98 times.
✓ Branch 4 taken 41877 times.
✓ Branch 5 taken 1933 times.
|
43810 | if (trx && UNIV_UNLIKELY(trx->stats.enabled())) return (trx); |
| 3326 | 1933 | return (nullptr); | |
| 3327 | } | ||
| 3328 | |||
| 3329 | /** InnoDB transaction object that is currently associated with THD is | ||
| 3330 | replaced with that of the 2nd argument. The previous value is | ||
| 3331 | returned through the 3rd argument's buffer, unless it's NULL. When | ||
| 3332 | the buffer is not provided (value NULL) that should mean the caller | ||
| 3333 | restores previously saved association so the current trx has to be | ||
| 3334 | additionally freed from all association with MYSQL. | ||
| 3335 | |||
| 3336 | @param[in,out] thd MySQL thread handle | ||
| 3337 | @param[in] new_trx_arg replacement trx_t | ||
| 3338 | @param[in,out] ptr_trx_arg pointer to a buffer to store old trx_t */ | ||
| 3339 | 1312 | static void innodb_replace_trx_in_thd(THD *thd, void *new_trx_arg, | |
| 3340 | void **ptr_trx_arg) { | ||
| 3341 |
1/2✓ Branch 0 taken 1312 times.
✗ Branch 1 not taken.
|
1312 | DBUG_TRACE; |
| 3342 |
1/2✓ Branch 0 taken 1312 times.
✗ Branch 1 not taken.
|
1312 | trx_t *&trx = thd_to_trx(thd); |
| 3343 | |||
| 3344 |
5/8✓ Branch 0 taken 350 times.
✓ Branch 1 taken 962 times.
✓ Branch 2 taken 350 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 350 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1312 times.
|
1312 | ut_ad(new_trx_arg == nullptr || (((trx_t *)new_trx_arg)->mysql_thd == thd && |
| 3345 | !((trx_t *)new_trx_arg)->is_recovered)); | ||
| 3346 | |||
| 3347 |
2/2✓ Branch 0 taken 357 times.
✓ Branch 1 taken 955 times.
|
1312 | if (ptr_trx_arg) { |
| 3348 | 357 | *ptr_trx_arg = trx; | |
| 3349 | |||
| 3350 |
5/8✓ Branch 0 taken 351 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 351 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 351 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 357 times.
|
357 | ut_ad(trx == nullptr || (trx->mysql_thd == thd && !trx->is_recovered)); |
| 3351 | |||
| 3352 |
2/2✓ Branch 0 taken 672 times.
✓ Branch 1 taken 283 times.
|
955 | } else if (trx != nullptr) { |
| 3353 |
2/4✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 672 times.
|
672 | ut_ad(trx_can_be_handled_by_current_thread_or_is_hp_victim(trx)); |
| 3354 |
2/2✓ Branch 0 taken 73 times.
✓ Branch 1 taken 599 times.
|
672 | if (trx->state.load(std::memory_order_relaxed) == TRX_STATE_NOT_STARTED) { |
| 3355 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | ut_ad(thd == trx->mysql_thd); |
| 3356 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | ut_ad(!trx_is_registered_for_2pc(trx)); |
| 3357 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | trx_free_for_mysql(trx); |
| 3358 | } else { | ||
| 3359 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
|
599 | ut_ad(thd == trx->mysql_thd); |
| 3360 |
2/4✓ Branch 0 taken 599 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 599 times.
|
599 | ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED)); |
| 3361 | /* The choice not to disconnect transaction when | ||
| 3362 | trx_is_redo_rseg_updated(trx) is false is copied from | ||
| 3363 | the existing detach logic for prepared XA | ||
| 3364 | transactions in innobase_close_connection(). | ||
| 3365 | If transaction did not modify anything, rolling it back doesn't modify | ||
| 3366 | the db, but lets us deregister and free the trx object to conserve | ||
| 3367 | resources, while still allowing XA COMMIT it in the future, as it | ||
| 3368 | succeeds on missing xids. */ | ||
| 3369 |
2/2✓ Branch 0 taken 591 times.
✓ Branch 1 taken 8 times.
|
599 | if (trx_is_redo_rseg_updated(trx)) { |
| 3370 |
1/2✓ Branch 0 taken 591 times.
✗ Branch 1 not taken.
|
591 | trx_disconnect_prepared(trx); |
| 3371 | } else { | ||
| 3372 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | trx_rollback_for_mysql(trx); |
| 3373 | 8 | trx_deregister_from_2pc(trx); | |
| 3374 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | trx_free_for_mysql(trx); |
| 3375 | } | ||
| 3376 | } | ||
| 3377 | } | ||
| 3378 | 1312 | trx = static_cast<trx_t *>(new_trx_arg); | |
| 3379 | 1312 | } | |
| 3380 | |||
| 3381 | /** Note that a transaction has been registered with MySQL 2PC coordinator. */ | ||
| 3382 | 108278428 | static inline void trx_register_for_2pc(trx_t *trx) /* in: transaction */ | |
| 3383 | { | ||
| 3384 | 108278428 | trx->is_registered = true; | |
| 3385 | 108278428 | } | |
| 3386 | |||
| 3387 | 21373691 | static inline void trx_deregister_from_2pc(trx_t *trx) { | |
| 3388 | 21373691 | trx->is_registered = false; | |
| 3389 | 21373691 | } | |
| 3390 | |||
| 3391 | /** Copy table flags from MySQL's HA_CREATE_INFO into an InnoDB table object. | ||
| 3392 | Those flags are stored in .frm file and end up in the MySQL table object, | ||
| 3393 | but are frequently used inside InnoDB so we keep their copies into the | ||
| 3394 | InnoDB table object. */ | ||
| 3395 | 348251 | static void innobase_copy_frm_flags_from_create_info( | |
| 3396 | dict_table_t *innodb_table, /*!< in/out: InnoDB table */ | ||
| 3397 | const HA_CREATE_INFO *create_info) /*!< in: create info */ | ||
| 3398 | { | ||
| 3399 | bool ps_on; | ||
| 3400 | bool ps_off; | ||
| 3401 | |||
| 3402 |
2/2✓ Branch 0 taken 153515 times.
✓ Branch 1 taken 194736 times.
|
348251 | if (innodb_table->is_temporary()) { |
| 3403 | /* Temp tables do not use persistent stats. */ | ||
| 3404 | 153515 | ps_on = false; | |
| 3405 | 153515 | ps_off = true; | |
| 3406 | } else { | ||
| 3407 | 194736 | ps_on = create_info->table_options & HA_OPTION_STATS_PERSISTENT; | |
| 3408 | 194736 | ps_off = create_info->table_options & HA_OPTION_NO_STATS_PERSISTENT; | |
| 3409 | } | ||
| 3410 | |||
| 3411 | 348251 | dict_stats_set_persistent(innodb_table, ps_on, ps_off); | |
| 3412 | |||
| 3413 | 348251 | dict_stats_auto_recalc_set( | |
| 3414 | 348251 | innodb_table, create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON, | |
| 3415 | 348251 | create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF); | |
| 3416 | |||
| 3417 | 348251 | innodb_table->stats_sample_pages = create_info->stats_sample_pages; | |
| 3418 | 348251 | } | |
| 3419 | |||
| 3420 | /** Copy table flags from MySQL's TABLE_SHARE into an InnoDB table object. | ||
| 3421 | Those flags are stored in .frm file and end up in the MySQL table object, | ||
| 3422 | but are frequently used inside InnoDB so we keep their copies into the | ||
| 3423 | InnoDB table object. */ | ||
| 3424 | 4179730 | void innobase_copy_frm_flags_from_table_share( | |
| 3425 | dict_table_t *innodb_table, /*!< in/out: InnoDB table */ | ||
| 3426 | const TABLE_SHARE *table_share) /*!< in: table share */ | ||
| 3427 | { | ||
| 3428 | bool ps_on; | ||
| 3429 | bool ps_off; | ||
| 3430 | |||
| 3431 |
2/2✓ Branch 0 taken 273144 times.
✓ Branch 1 taken 3906586 times.
|
4179730 | if (innodb_table->is_temporary()) { |
| 3432 | /* Temp tables do not use persistent stats */ | ||
| 3433 | 273144 | ps_on = false; | |
| 3434 | 273144 | ps_off = true; | |
| 3435 | } else { | ||
| 3436 | 3906586 | ps_on = table_share->db_create_options & HA_OPTION_STATS_PERSISTENT; | |
| 3437 | 3906586 | ps_off = table_share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT; | |
| 3438 | } | ||
| 3439 | |||
| 3440 | 4179730 | dict_stats_set_persistent(innodb_table, ps_on, ps_off); | |
| 3441 | |||
| 3442 | 4179730 | dict_stats_auto_recalc_set( | |
| 3443 | 4179730 | innodb_table, table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON, | |
| 3444 | 4179730 | table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF); | |
| 3445 | |||
| 3446 | 4179730 | innodb_table->stats_sample_pages = table_share->stats_sample_pages; | |
| 3447 | 4179730 | } | |
| 3448 | |||
| 3449 | 850386 | int ha_innobase::srv_concurrency_enter() { | |
| 3450 | 850386 | auto err = innobase_srv_conc_enter_innodb(m_prebuilt); | |
| 3451 | |||
| 3452 | 850386 | trx_t *trx = m_prebuilt->trx; | |
| 3453 | 850386 | return convert_error_code_to_mysql(err, 0, trx->mysql_thd); | |
| 3454 | } | ||
| 3455 | |||
| 3456 | 850386 | void ha_innobase::srv_concurrency_exit() { | |
| 3457 | 850386 | innobase_srv_conc_exit_innodb(m_prebuilt); | |
| 3458 | 850386 | } | |
| 3459 | |||
| 3460 | /** Construct ha_innobase handler. */ | ||
| 3461 | |||
| 3462 | 9236925 | ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg) | |
| 3463 | : handler(hton, table_arg), | ||
| 3464 | 9236930 | m_ds_mrr(this), | |
| 3465 | 9236928 | m_prebuilt(), | |
| 3466 | 9236928 | m_user_thd(), | |
| 3467 | 9236928 | m_int_table_flags( | |
| 3468 | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_CAN_SQL_HANDLER | | ||
| 3469 | HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_PRIMARY_KEY_IN_READ_INDEX | | ||
| 3470 | HA_BINLOG_ROW_CAPABLE | HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ | | ||
| 3471 | HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT | HA_CAN_FULLTEXT_EXT | | ||
| 3472 | HA_CAN_FULLTEXT_HINTS | HA_CAN_EXPORT | HA_CAN_RTREEKEYS | | ||
| 3473 | HA_NO_READ_LOCAL_LOCK | HA_GENERATED_COLUMNS | | ||
| 3474 | HA_ATTACHABLE_TRX_COMPATIBLE | HA_CAN_INDEX_VIRTUAL_GENERATED_COLUMN | | ||
| 3475 | HA_DESCENDING_INDEX | HA_MULTI_VALUED_KEY_SUPPORT | | ||
| 3476 | HA_BLOB_PARTIAL_UPDATE | HA_SUPPORTS_GEOGRAPHIC_GEOMETRY_COLUMN | | ||
| 3477 | HA_SUPPORTS_DEFAULT_EXPRESSION | HA_ONLINE_ANALYZE), | ||
| 3478 | 9236928 | m_start_of_scan(), | |
| 3479 | 9236928 | m_stored_select_lock_type(LOCK_NONE_UNSET), | |
| 3480 | 9236925 | m_mysql_has_locked() {} | |
| 3481 | |||
| 3482 | /** Updates the user_thd field in a handle and also allocates a new InnoDB | ||
| 3483 | transaction handle if needed, and updates the transaction fields in the | ||
| 3484 | m_prebuilt struct. */ | ||
| 3485 | 1175200009 | void ha_innobase::update_thd(THD *thd) /*!< in: thd to use the handle */ | |
| 3486 | { | ||
| 3487 |
1/2✓ Branch 0 taken 1175212620 times.
✗ Branch 1 not taken.
|
1175200009 | DBUG_TRACE; |
| 3488 |
5/8✓ Branch 0 taken 1175209376 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1175206975 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69665 times.
✓ Branch 5 taken 1175137310 times.
✓ Branch 6 taken 69665 times.
✗ Branch 7 not taken.
|
1175212620 | DBUG_PRINT("ha_innobase::update_thd", |
| 3489 | ("user_thd: %p -> %p", m_user_thd, thd)); | ||
| 3490 | |||
| 3491 | /* The table should have been opened in ha_innobase::open(). */ | ||
| 3492 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1175205319 times.
|
1175206975 | assert(m_prebuilt->table->n_ref_count > 0); |
| 3493 | |||
| 3494 |
1/2✓ Branch 0 taken 1175211279 times.
✗ Branch 1 not taken.
|
1175205319 | trx_t *trx = check_trx_exists(thd); |
| 3495 | |||
| 3496 |
1/2✓ Branch 0 taken 1175205101 times.
✗ Branch 1 not taken.
|
1175211279 | TrxInInnoDB trx_in_innodb(trx); |
| 3497 | |||
| 3498 |
2/2✓ Branch 0 taken 24325307 times.
✓ Branch 1 taken 1150879794 times.
|
1175205101 | if (m_prebuilt->trx != trx) { |
| 3499 |
1/2✓ Branch 0 taken 24325160 times.
✗ Branch 1 not taken.
|
24325307 | row_update_prebuilt_trx(m_prebuilt, trx); |
| 3500 | } | ||
| 3501 | |||
| 3502 | 1175204954 | m_user_thd = thd; | |
| 3503 | |||
| 3504 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1175204954 times.
|
1175204954 | assert(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 3505 |
2/4✓ Branch 0 taken 1175205356 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1175205356 times.
|
1175204954 | assert(m_prebuilt->trx == thd_to_trx(m_user_thd)); |
| 3506 | 1175205356 | } | |
| 3507 | |||
| 3508 | /** Updates the user_thd field in a handle and also allocates a new InnoDB | ||
| 3509 | transaction handle if needed, and updates the transaction fields in the | ||
| 3510 | m_prebuilt struct. */ | ||
| 3511 | |||
| 3512 | 945636823 | void ha_innobase::update_thd() { | |
| 3513 | 945636823 | THD *thd = ha_thd(); | |
| 3514 | |||
| 3515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 945634090 times.
|
945637888 | ut_ad(EQ_CURRENT_THD(thd)); |
| 3516 | 945634090 | update_thd(thd); | |
| 3517 | 945640299 | } | |
| 3518 | |||
| 3519 | /** Registers an InnoDB transaction with the MySQL 2PC coordinator, so that | ||
| 3520 | the MySQL XA code knows to call the InnoDB prepare and commit, or rollback | ||
| 3521 | for the transaction. This MUST be called for every transaction for which | ||
| 3522 | the user may call commit or rollback. Calling this several times to register | ||
| 3523 | the same transaction is allowed, too. This function also registers the | ||
| 3524 | current SQL statement. */ | ||
| 3525 | 108278177 | void innobase_register_trx(handlerton *hton, /* in: Innobase handlerton */ | |
| 3526 | THD *thd, /* in: MySQL thd (connection) object */ | ||
| 3527 | trx_t *trx) /* in: transaction to register */ | ||
| 3528 | { | ||
| 3529 |
1/2✓ Branch 0 taken 108278641 times.
✗ Branch 1 not taken.
|
108278177 | const ulonglong trx_id = static_cast<ulonglong>(trx_get_id_for_print(trx)); |
| 3530 | |||
| 3531 |
1/2✓ Branch 0 taken 108279439 times.
✗ Branch 1 not taken.
|
108278641 | trans_register_ha(thd, false, hton, &trx_id); |
| 3532 | |||
| 3533 |
4/4✓ Branch 0 taken 20676243 times.
✓ Branch 1 taken 87602230 times.
✓ Branch 2 taken 1171050 times.
✓ Branch 3 taken 107107625 times.
|
128955884 | if (!trx_is_registered_for_2pc(trx) && |
| 3534 |
3/4✓ Branch 0 taken 20676445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1171014 times.
✓ Branch 3 taken 19505431 times.
|
20676243 | thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { |
| 3535 |
1/2✓ Branch 0 taken 1171246 times.
✗ Branch 1 not taken.
|
1171050 | trans_register_ha(thd, true, hton, &trx_id); |
| 3536 | } | ||
| 3537 | |||
| 3538 | 108278871 | trx_register_for_2pc(trx); | |
| 3539 | 108278763 | } | |
| 3540 | |||
| 3541 | /** Quote a standard SQL identifier like tablespace, index or column name. | ||
| 3542 | @param[in] file output stream | ||
| 3543 | @param[in] trx InnoDB transaction, or NULL | ||
| 3544 | @param[in] id identifier to quote */ | ||
| 3545 | 1188 | void innobase_quote_identifier(FILE *file, trx_t *trx, const char *id) { | |
| 3546 | const int q = | ||
| 3547 |
1/2✓ Branch 0 taken 1182 times.
✗ Branch 1 not taken.
|
1182 | trx != nullptr && trx->mysql_thd != nullptr |
| 3548 |
2/2✓ Branch 0 taken 1182 times.
✓ Branch 1 taken 6 times.
|
2370 | ? get_quote_char_for_identifier(trx->mysql_thd, id, strlen(id)) |
| 3549 | 1188 | : '`'; | |
| 3550 | |||
| 3551 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1188 times.
|
1188 | if (q == EOF) { |
| 3552 | ✗ | fputs(id, file); | |
| 3553 | } else { | ||
| 3554 | 1188 | putc(q, file); | |
| 3555 | |||
| 3556 |
2/2✓ Branch 0 taken 4976 times.
✓ Branch 1 taken 1188 times.
|
6164 | while (int c = *id++) { |
| 3557 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4976 times.
|
4976 | if (c == q) { |
| 3558 | ✗ | putc(c, file); | |
| 3559 | } | ||
| 3560 | 4976 | putc(c, file); | |
| 3561 | 4976 | } | |
| 3562 | |||
| 3563 | 1188 | putc(q, file); | |
| 3564 | } | ||
| 3565 | 1188 | } | |
| 3566 | |||
| 3567 | /** Convert a table name to the MySQL system_charset_info (UTF-8) | ||
| 3568 | and quote it. | ||
| 3569 | @param[out] buf buffer for converted identifier | ||
| 3570 | @param[in] buflen length of buf, in bytes | ||
| 3571 | @param[in] id identifier to convert | ||
| 3572 | @param[in] idlen length of id, in bytes | ||
| 3573 | @param[in] thd MySQL connection thread, or NULL | ||
| 3574 | @return pointer to the end of buf */ | ||
| 3575 | 26745 | static char *innobase_convert_identifier(char *buf, ulint buflen, | |
| 3576 | const char *id, ulint idlen, | ||
| 3577 | THD *thd) { | ||
| 3578 | 26745 | const char *s = id; | |
| 3579 | |||
| 3580 | char nz[MAX_TABLE_NAME_LEN + 1]; | ||
| 3581 | char nz2[MAX_TABLE_NAME_LEN + 1]; | ||
| 3582 | |||
| 3583 | /* Decode the table name. The MySQL function expects | ||
| 3584 | a NUL-terminated string. The input and output strings | ||
| 3585 | buffers must not be shared. */ | ||
| 3586 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26745 times.
|
26745 | ut_a(idlen <= MAX_TABLE_NAME_LEN); |
| 3587 | 26745 | memcpy(nz, id, idlen); | |
| 3588 | 26745 | nz[idlen] = 0; | |
| 3589 | |||
| 3590 | 26745 | s = nz2; | |
| 3591 | idlen = | ||
| 3592 |
1/2✓ Branch 0 taken 26745 times.
✗ Branch 1 not taken.
|
26745 | explain_filename(thd, nz, nz2, sizeof nz2, EXPLAIN_PARTITIONS_AS_COMMENT); |
| 3593 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 26735 times.
|
26745 | if (idlen > buflen) { |
| 3594 | 10 | idlen = buflen; | |
| 3595 | } | ||
| 3596 | 26745 | memcpy(buf, s, idlen); | |
| 3597 | 26745 | return (buf + idlen); | |
| 3598 | } | ||
| 3599 | |||
| 3600 | /** Convert a table name to the MySQL system_charset_info (UTF-8). | ||
| 3601 | @return pointer to the end of buf */ | ||
| 3602 | 13599 | char *innobase_convert_name( | |
| 3603 | char *buf, /*!< out: buffer for converted identifier */ | ||
| 3604 | ulint buflen, /*!< in: length of buf, in bytes */ | ||
| 3605 | const char *id, /*!< in: table name to convert */ | ||
| 3606 | ulint idlen, /*!< in: length of id, in bytes */ | ||
| 3607 | THD *thd) /*!< in: MySQL connection thread, or NULL */ | ||
| 3608 | { | ||
| 3609 | 13599 | char *s = buf; | |
| 3610 | 13599 | const char *bufend = buf + buflen; | |
| 3611 | |||
| 3612 | 13599 | const char *slash = (const char *)memchr(id, '/', idlen); | |
| 3613 | |||
| 3614 |
2/2✓ Branch 0 taken 446 times.
✓ Branch 1 taken 13153 times.
|
13599 | if (slash == nullptr) { |
| 3615 | 446 | return (innobase_convert_identifier(buf, buflen, id, idlen, thd)); | |
| 3616 | } | ||
| 3617 | |||
| 3618 | /* Print the database name and table name separately. */ | ||
| 3619 | 13153 | s = innobase_convert_identifier(s, bufend - s, id, slash - id, thd); | |
| 3620 |
2/2✓ Branch 0 taken 13146 times.
✓ Branch 1 taken 7 times.
|
13153 | if (s < bufend) { |
| 3621 | 13146 | *s++ = '.'; | |
| 3622 | 13146 | s = innobase_convert_identifier(s, bufend - s, slash + 1, | |
| 3623 | 13146 | idlen - (slash - id) - 1, thd); | |
| 3624 | } | ||
| 3625 | |||
| 3626 | 13153 | return (s); | |
| 3627 | } | ||
| 3628 | |||
| 3629 | /** A wrapper function of innobase_convert_name(), convert a table name | ||
| 3630 | to the MySQL system_charset_info (UTF-8) and quote it if needed. | ||
| 3631 | @param[out] buf Buffer for converted identifier | ||
| 3632 | @param[in] buflen Length of buf, in bytes | ||
| 3633 | @param[in] name Table name to format */ | ||
| 3634 | 147 | void innobase_format_name(char *buf, ulint buflen, const char *name) { | |
| 3635 | const char *bufend; | ||
| 3636 | |||
| 3637 | 147 | bufend = innobase_convert_name(buf, buflen, name, strlen(name), nullptr); | |
| 3638 | |||
| 3639 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
|
147 | ut_ad((ulint)(bufend - buf) < buflen); |
| 3640 | |||
| 3641 | 147 | buf[bufend - buf] = '\0'; | |
| 3642 | 147 | } | |
| 3643 | |||
| 3644 | /** Determines if the currently running transaction has been interrupted. | ||
| 3645 | @return true if interrupted */ | ||
| 3646 | 457133775 | bool trx_is_interrupted(const trx_t *trx) /*!< in: transaction */ | |
| 3647 | { | ||
| 3648 |
6/6✓ Branch 0 taken 457004672 times.
✓ Branch 1 taken 129103 times.
✓ Branch 2 taken 457004583 times.
✓ Branch 3 taken 89 times.
✓ Branch 4 taken 77 times.
✓ Branch 5 taken 457004380 times.
|
457133775 | return (trx && trx->mysql_thd && thd_killed(trx->mysql_thd)); |
| 3649 | } | ||
| 3650 | |||
| 3651 | /** Determines if the currently running transaction is in strict mode. | ||
| 3652 | @return true if strict */ | ||
| 3653 | 374251 | bool trx_is_strict(trx_t *trx) /*!< in: transaction */ | |
| 3654 | { | ||
| 3655 | /* Relax strict check if table is in truncate create table */ | ||
| 3656 |
4/6✓ Branch 0 taken 374251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 374251 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 370628 times.
✓ Branch 5 taken 3623 times.
|
744879 | return (trx && trx->mysql_thd && THDVAR(trx->mysql_thd, strict_mode) && |
| 3657 |
2/2✓ Branch 0 taken 338794 times.
✓ Branch 1 taken 31834 times.
|
744879 | (!trx->in_truncate)); |
| 3658 | } | ||
| 3659 | |||
| 3660 | #ifdef WITH_WSREP | ||
| 3661 | /** Determines if the currently running transaction is a wsrep transaction. | ||
| 3662 | @return true if transaction is a wsrep transaction */ | ||
| 3663 | 1943 | bool trx_is_wsrep_trx(const trx_t *trx) /*!< in: transaction */ | |
| 3664 | { | ||
| 3665 |
3/4✓ Branch 0 taken 1943 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 375 times.
✓ Branch 3 taken 1568 times.
|
1943 | return (trx && wsrep_on(trx->mysql_thd)); |
| 3666 | } | ||
| 3667 | #endif /* WITH_WSREP */ | ||
| 3668 | |||
| 3669 | /** Resets some fields of a m_prebuilt struct. The template is used in fast | ||
| 3670 | retrieval of just those column values MySQL needs in its processing. */ | ||
| 3671 | 421652864 | void ha_innobase::reset_template(void) { | |
| 3672 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 421654788 times.
|
421652864 | ut_ad(m_prebuilt->magic_n == ROW_PREBUILT_ALLOCATED); |
| 3673 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 421655317 times.
|
421654788 | ut_ad(m_prebuilt->magic_n2 == m_prebuilt->magic_n); |
| 3674 | |||
| 3675 | /* Force table to be freed in close_thread_table(). */ | ||
| 3676 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 421655347 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
421655317 | DBUG_EXECUTE_IF( |
| 3677 | "free_table_in_fts_query", | ||
| 3678 | if (m_prebuilt->in_fts_query) { table->invalidate_dict(); }); | ||
| 3679 | |||
| 3680 | 421655347 | m_prebuilt->keep_other_fields_on_keyread = 0; | |
| 3681 | 421655347 | m_prebuilt->read_just_key = 0; | |
| 3682 | 421655347 | m_prebuilt->in_fts_query = false; | |
| 3683 | 421655347 | m_prebuilt->m_end_range = false; | |
| 3684 | |||
| 3685 | /* Reset index condition pushdown state. */ | ||
| 3686 |
2/2✓ Branch 0 taken 2431 times.
✓ Branch 1 taken 421652916 times.
|
421655347 | if (m_prebuilt->idx_cond) { |
| 3687 | 2431 | m_prebuilt->idx_cond = false; | |
| 3688 | 2431 | m_prebuilt->idx_cond_n_cols = 0; | |
| 3689 | /* Invalidate m_prebuilt->mysql_template | ||
| 3690 | in ha_innobase::write_row(). */ | ||
| 3691 | 2431 | m_prebuilt->template_type = ROW_MYSQL_NO_TEMPLATE; | |
| 3692 | } | ||
| 3693 | 421655347 | } | |
| 3694 | |||
| 3695 | /** Call this when you have opened a new table handle in HANDLER, before you | ||
| 3696 | call index_read_map() etc. Actually, we can let the cursor stay open even | ||
| 3697 | over a transaction commit! Then you should call this before every operation, | ||
| 3698 | fetch next etc. This function inits the necessary things even after a | ||
| 3699 | transaction commit. */ | ||
| 3700 | |||
| 3701 | 74184 | void ha_innobase::init_table_handle_for_HANDLER(void) { | |
| 3702 | /* If current thd does not yet have a trx struct, create one. | ||
| 3703 | If the current handle does not yet have a m_prebuilt struct, create | ||
| 3704 | one. Update the trx pointers in the m_prebuilt struct. Normally | ||
| 3705 | this operation is done in external_lock. */ | ||
| 3706 | |||
| 3707 |
2/4✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74184 times.
✗ Branch 3 not taken.
|
74184 | update_thd(ha_thd()); |
| 3708 | |||
| 3709 | /* Initialize the m_prebuilt struct much like it would be inited in | ||
| 3710 | external_lock */ | ||
| 3711 | |||
| 3712 |
1/2✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
|
74184 | innobase_srv_conc_force_exit_innodb(m_prebuilt->trx); |
| 3713 | |||
| 3714 | /* If the transaction is not started yet, start it */ | ||
| 3715 | |||
| 3716 |
1/2✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
|
74184 | trx_start_if_not_started_xa(m_prebuilt->trx, false, UT_LOCATION_HERE); |
| 3717 | |||
| 3718 |
1/2✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
|
74184 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 3719 | |||
| 3720 | /* Assign a read view if the transaction does not have it yet */ | ||
| 3721 | |||
| 3722 |
1/2✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
|
74184 | trx_assign_read_view(m_prebuilt->trx); |
| 3723 | |||
| 3724 |
1/2✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
|
74184 | innobase_register_trx(ht, m_user_thd, m_prebuilt->trx); |
| 3725 | |||
| 3726 | /* We did the necessary inits in this function, no need to repeat them | ||
| 3727 | in row_search_for_mysql */ | ||
| 3728 | |||
| 3729 | 74184 | m_prebuilt->sql_stat_start = false; | |
| 3730 | |||
| 3731 | /* We let HANDLER always to do the reads as consistent reads, even | ||
| 3732 | if the trx isolation level would have been specified as SERIALIZABLE */ | ||
| 3733 | |||
| 3734 | 74184 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 3735 | 74184 | m_prebuilt->select_mode = SELECT_ORDINARY; | |
| 3736 | 74184 | m_stored_select_lock_type = LOCK_NONE; | |
| 3737 | |||
| 3738 | /* Always fetch all columns in the index record */ | ||
| 3739 | |||
| 3740 | 74184 | m_prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS; | |
| 3741 | |||
| 3742 | /* We want always to fetch all columns in the whole row? Or do | ||
| 3743 | we???? */ | ||
| 3744 | |||
| 3745 | 74184 | m_prebuilt->used_in_HANDLER = true; | |
| 3746 | |||
| 3747 |
1/2✓ Branch 0 taken 74184 times.
✗ Branch 1 not taken.
|
74184 | reset_template(); |
| 3748 | 74184 | } | |
| 3749 | |||
| 3750 | /** Free any resources that were allocated and return failure. | ||
| 3751 | @return always return 1 */ | ||
| 3752 | 101 | static int innodb_init_abort() { | |
| 3753 |
1/2✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
|
101 | DBUG_TRACE; |
| 3754 |
1/2✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
|
101 | srv_shutdown_exit_threads(); |
| 3755 |
1/2✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
|
101 | innodb_space_shutdown(); |
| 3756 |
1/2✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
|
101 | innobase::component_services::deinitialize_service_handles(); |
| 3757 |
1/2✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
|
101 | release_plugin_services(); |
| 3758 | 101 | return 1; | |
| 3759 | 101 | } | |
| 3760 | |||
| 3761 | /** Open or create InnoDB data files. | ||
| 3762 | @param[in] dict_init_mode whether to create or open the files | ||
| 3763 | @param[in,out] tablespaces predefined tablespaces created by the DDSE | ||
| 3764 | @return 0 on success, 1 on failure */ | ||
| 3765 | [[nodiscard]] static int innobase_init_files( | ||
| 3766 | dict_init_mode_t dict_init_mode, | ||
| 3767 | List<const Plugin_tablespace> *tablespaces, | ||
| 3768 | bool &is_dd_encrypted); | ||
| 3769 | |||
| 3770 | /** Initialize InnoDB for being used to store the DD tables. | ||
| 3771 | Create the required files according to the dict_init_mode. | ||
| 3772 | Create strings representing the required DDSE tables, i.e., | ||
| 3773 | tables that InnoDB expects to exist in the DD, | ||
| 3774 | and add them to the appropriate out parameter. | ||
| 3775 | |||
| 3776 | @param[in] dict_init_mode How to initialize files | ||
| 3777 | |||
| 3778 | @param[in] version Target DD version if a new server | ||
| 3779 | is being installed. | ||
| 3780 | 0 if restarting an existing server. | ||
| 3781 | |||
| 3782 | @param[out] tables List of SQL DDL statements | ||
| 3783 | for creating DD tables that | ||
| 3784 | are needed by the DDSE. | ||
| 3785 | |||
| 3786 | @param[out] tablespaces List of meta data for predefined | ||
| 3787 | tablespaces created by the DDSE. | ||
| 3788 | |||
| 3789 | @retval true An error occurred. | ||
| 3790 | @retval false Success - no errors. */ | ||
| 3791 | static bool innobase_ddse_dict_init(dict_init_mode_t dict_init_mode, | ||
| 3792 | uint version, | ||
| 3793 | List<const dd::Object_table> *tables, | ||
| 3794 | List<const Plugin_tablespace> *tablespaces); | ||
| 3795 | |||
| 3796 | /** Save the state of undo tablespaces from the dd to the undo::Tablespace | ||
| 3797 | @param[in] space_id tablespace ID | ||
| 3798 | @param[in] dd_space dd::Tablespace object | ||
| 3799 | @return true if success and false if the undo tablespace state is not saved. */ | ||
| 3800 | 18913 | bool apply_dd_undo_state(space_id_t space_id, const dd::Tablespace *dd_space) { | |
| 3801 | 18913 | bool success = true; | |
| 3802 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18913 times.
|
18913 | if (!fsp_is_undo_tablespace(space_id)) { |
| 3803 | ✗ | return (success); | |
| 3804 | } | ||
| 3805 | |||
| 3806 | /* Get the state of undo tablespaces from the DD. */ | ||
| 3807 | 18913 | dd_space_states state = dd_tablespace_get_state_enum(dd_space, space_id); | |
| 3808 | |||
| 3809 | 18913 | undo::spaces->s_lock(); | |
| 3810 | |||
| 3811 | 18913 | space_id_t space_num = undo::id2num(space_id); | |
| 3812 | 18913 | undo::Tablespace *undo_space = undo::spaces->find(space_num); | |
| 3813 | |||
| 3814 |
3/5✓ Branch 0 taken 18851 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
18913 | switch (state) { |
| 3815 | 18851 | case DD_SPACE_STATE__LAST: | |
| 3816 | /* If the "state" key is missing the DD might have been built with | ||
| 3817 | an older version. */ | ||
| 3818 | case DD_SPACE_STATE_ACTIVE: | ||
| 3819 | /* Explicit undo spaces with no undo logs are set empty during | ||
| 3820 | startup to avoid getting undo. */ | ||
| 3821 |
2/2✓ Branch 0 taken 203 times.
✓ Branch 1 taken 18648 times.
|
18851 | if (undo_space->is_empty()) { |
| 3822 | 203 | undo_space->set_active(); | |
| 3823 | } | ||
| 3824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18851 times.
|
18851 | ut_ad(undo_space->is_active()); |
| 3825 | 18851 | break; | |
| 3826 | 2 | case DD_SPACE_STATE_INACTIVE: | |
| 3827 | 2 | undo_space->set_inactive_explicit(); | |
| 3828 | 2 | srv_wake_purge_thread_if_not_active(); | |
| 3829 | |||
| 3830 | 2 | break; | |
| 3831 | 60 | case DD_SPACE_STATE_EMPTY: | |
| 3832 | 60 | undo_space->set_empty(); | |
| 3833 | 60 | break; | |
| 3834 | ✗ | case DD_SPACE_STATE_NORMAL: | |
| 3835 | case DD_SPACE_STATE_DISCARDED: | ||
| 3836 | case DD_SPACE_STATE_CORRUPTED: | ||
| 3837 | ✗ | success = false; | |
| 3838 | ✗ | break; | |
| 3839 | } | ||
| 3840 | |||
| 3841 | 18913 | undo::spaces->s_unlock(); | |
| 3842 | |||
| 3843 | 18913 | return (success); | |
| 3844 | } | ||
| 3845 | |||
| 3846 | /** Initialize the set of hard coded DD table ids. | ||
| 3847 | @param[in] dd_table_id Table id of DD table. */ | ||
| 3848 | static void innobase_dict_register_dd_table_id(dd::Object_id dd_table_id); | ||
| 3849 | |||
| 3850 | /** Validate the DD tablespace data against what's read during the | ||
| 3851 | directory scan on startup. */ | ||
| 3852 | class Validate_files { | ||
| 3853 | using DD_tablespaces = std::vector<const dd::Tablespace *>; | ||
| 3854 | using Const_iter = DD_tablespaces::const_iterator; | ||
| 3855 | |||
| 3856 | public: | ||
| 3857 | /** Constructor */ | ||
| 3858 | 9331 | Validate_files() | |
| 3859 | 9331 | : m_mutex(), | |
| 3860 | 9331 | m_space_max_id(), | |
| 3861 | 9331 | m_n_to_check(), | |
| 3862 | 9331 | m_n_threads(), | |
| 3863 | 9331 | m_start_time(std::chrono::steady_clock::time_point{}), | |
| 3864 | 9331 | m_n_validated(), | |
| 3865 | 9331 | m_n_skipped(), | |
| 3866 | 9331 | m_n_moved(), | |
| 3867 | 9331 | m_n_missing(), | |
| 3868 | 9331 | m_n_deleted(), | |
| 3869 | 9331 | m_n_errors() {} | |
| 3870 | |||
| 3871 | /** Validate the discovered tablespaces against the DD and attempt to open | ||
| 3872 | any DD tablespace not already open using a Parallel For Loop (par_for). | ||
| 3873 | @param[in] tablespaces Tablespace files read from the DD | ||
| 3874 | @return DB_SUCCESS if all OK */ | ||
| 3875 | [[nodiscard]] dberr_t validate(const DD_tablespaces &tablespaces); | ||
| 3876 | |||
| 3877 | private: | ||
| 3878 | /** Validate a range of tablespaces from the DD. | ||
| 3879 | 1. Compare the discovered files against those known to the dictionary. | ||
| 3880 | 2. Open any tablespace known to the DD but not discovered and opened | ||
| 3881 | from the known directories. | ||
| 3882 | 3. Update the DD if a tablespace has moved. | ||
| 3883 | 4. Update the DD if an undo tablespace was truncated and replaced. | ||
| 3884 | 5. If innodb_validate_tablespace_paths is set and this is not called | ||
| 3885 | while in recovery, only validate undo tablespaces. | ||
| 3886 | 6. Track the number of skipped, moved, missing and deleted tablespaces. | ||
| 3887 | 7. Return failure for any unexpected error. | ||
| 3888 | @param[in] begin Start of the slice | ||
| 3889 | @param[in] end End of the slice | ||
| 3890 | @param[in] thread_id Thread ID */ | ||
| 3891 | void check(const Const_iter &begin, const Const_iter &end, size_t thread_id); | ||
| 3892 | |||
| 3893 | /** @return true if there were failures. */ | ||
| 3894 | 18662 | bool failed() const { return (m_n_errors.load() != 0); } | |
| 3895 | |||
| 3896 | /** @return the maximum tablespace ID found. */ | ||
| 3897 | 9331 | space_id_t get_space_max_id() const { return (m_space_max_id); } | |
| 3898 | |||
| 3899 | private: | ||
| 3900 | /** Mutex protecting the parallel check. */ | ||
| 3901 | std::mutex m_mutex; | ||
| 3902 | |||
| 3903 | /** Maximum tablespace ID found. */ | ||
| 3904 | space_id_t m_space_max_id; | ||
| 3905 | |||
| 3906 | /** Number of tablespaces to check. */ | ||
| 3907 | size_t m_n_to_check; | ||
| 3908 | |||
| 3909 | /** Number of threads used in the parallel for. */ | ||
| 3910 | size_t m_n_threads; | ||
| 3911 | |||
| 3912 | /** The time when Validate_files::validate() starts or the last time | ||
| 3913 | one of the threads reported progress. */ | ||
| 3914 | std::atomic<std::chrono::steady_clock::time_point> m_start_time; | ||
| 3915 | static_assert(decltype(m_start_time)::is_always_lock_free); | ||
| 3916 | |||
| 3917 | /** Number of tablespaces validated. */ | ||
| 3918 | std::atomic_size_t m_n_validated; | ||
| 3919 | |||
| 3920 | /** Number of tablespaces skipped. */ | ||
| 3921 | std::atomic_size_t m_n_skipped; | ||
| 3922 | |||
| 3923 | /** Number of tablespaces moved. */ | ||
| 3924 | std::atomic_size_t m_n_moved; | ||
| 3925 | |||
| 3926 | /** Number of tablespaces missing. */ | ||
| 3927 | std::atomic_size_t m_n_missing; | ||
| 3928 | |||
| 3929 | /** Number of tablespaces deleted. */ | ||
| 3930 | std::atomic_size_t m_n_deleted; | ||
| 3931 | |||
| 3932 | /** Number of threads that failed. */ | ||
| 3933 | std::atomic_size_t m_n_errors; | ||
| 3934 | }; | ||
| 3935 | |||
| 3936 | 9331 | void Validate_files::check(const Const_iter &begin, const Const_iter &end, | |
| 3937 | size_t thread_id) { | ||
| 3938 | 9331 | const auto sys_space_name = dict_sys_t::s_sys_space_name; | |
| 3939 | |||
| 3940 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | auto heap = mem_heap_create(FN_REFLEN * 2 + 1, UT_LOCATION_HERE); |
| 3941 | |||
| 3942 | /* If the setting for innodb_validate_tablespace_paths is NO and we are | ||
| 3943 | not in recovery, then only validate undo tablespaces. */ | ||
| 3944 | 9331 | const bool ibd_validate = | |
| 3945 |
4/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9320 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
|
9331 | srv_validate_tablespace_paths || recv_needed_recovery; |
| 3946 | |||
| 3947 | 9331 | std::string prefix; | |
| 3948 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
|
9331 | if (m_n_threads > 0) { |
| 3949 | ✗ | std::ostringstream msg; | |
| 3950 | ✗ | msg << "Thread# " << thread_id << " - "; | |
| 3951 | ✗ | prefix = msg.str(); | |
| 3952 | } | ||
| 3953 | |||
| 3954 |
2/2✓ Branch 0 taken 91262 times.
✓ Branch 1 taken 9331 times.
|
100593 | for (auto it = begin; it != end; ++it) { |
| 3955 | 91262 | const auto &dd_tablespace = *it; | |
| 3956 | |||
| 3957 |
3/6✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91262 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 91262 times.
|
91262 | if (std::chrono::steady_clock::now() - m_start_time.load() >= |
| 3958 | PRINT_INTERVAL) { | ||
| 3959 | ✗ | m_start_time = std::chrono::steady_clock::now(); | |
| 3960 | |||
| 3961 | ✗ | std::ostringstream msg; | |
| 3962 | |||
| 3963 | ✗ | if (m_n_threads) { | |
| 3964 | ✗ | msg << m_n_threads << "threads have validated "; | |
| 3965 | } else { | ||
| 3966 | ✗ | msg << "Validated "; | |
| 3967 | } | ||
| 3968 | |||
| 3969 | ✗ | msg << m_n_validated << " out of " << m_n_to_check | |
| 3970 | ✗ | << " tablespaces so far."; | |
| 3971 | |||
| 3972 | ✗ | if (m_n_skipped > 0) { | |
| 3973 | ✗ | msg << " Skipped=" << m_n_skipped << "."; | |
| 3974 | } | ||
| 3975 | ✗ | if (m_n_moved > 0) { | |
| 3976 | ✗ | msg << " Moved=" << m_n_moved << "."; | |
| 3977 | } | ||
| 3978 | ✗ | if (m_n_missing > 0) { | |
| 3979 | ✗ | msg << " Missing=" << m_n_missing << "."; | |
| 3980 | } | ||
| 3981 | ✗ | if (m_n_deleted > 0) { | |
| 3982 | ✗ | msg << " Deleted=" << m_n_deleted << "."; | |
| 3983 | } | ||
| 3984 | |||
| 3985 | ✗ | ib::info(ER_IB_MSG_525) << msg.str(); | |
| 3986 | } | ||
| 3987 | |||
| 3988 |
3/6✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91262 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 91262 times.
|
91262 | if (dd_tablespace->engine() != innobase_hton_name) { |
| 3989 | ✗ | ++m_n_skipped; | |
| 3990 | 50494 | continue; | |
| 3991 | } | ||
| 3992 | |||
| 3993 | 91262 | bool is_enc_in_progress{false}; | |
| 3994 |
1/2✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
|
91262 | const auto &p = dd_tablespace->se_private_data(); |
| 3995 |
1/2✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
|
91262 | const auto &o = dd_tablespace->options(); |
| 3996 |
1/2✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
|
91262 | const char *space_name = dd_tablespace->name().c_str(); |
| 3997 | 91262 | const auto se_key_value = dd_space_key_strings; | |
| 3998 | |||
| 3999 | /* There should be exactly one file name associated | ||
| 4000 | with each InnoDB tablespace, except innodb_system */ | ||
| 4001 | |||
| 4002 | space_id_t space_id; | ||
| 4003 |
3/6✓ Branch 0 taken 91262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91262 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 91262 times.
|
91262 | if (p.get(se_key_value[DD_SPACE_ID], &space_id)) { |
| 4004 | /* Failed to fetch the tablespace ID */ | ||
| 4005 | ✗ | ++m_n_errors; | |
| 4006 | ✗ | break; | |
| 4007 | } | ||
| 4008 | |||
| 4009 | /* If --innodb_validate_tablespace_paths=OFF and | ||
| 4010 | startup is not in recovery, then skip all IBD files. */ | ||
| 4011 |
7/8✓ Branch 0 taken 155 times.
✓ Branch 1 taken 91107 times.
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 137 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 137 times.
✓ Branch 7 taken 91125 times.
|
91262 | if (!ibd_validate && !fsp_is_undo_tablespace(space_id)) { |
| 4012 | 137 | ++m_n_skipped; | |
| 4013 | 137 | continue; | |
| 4014 | } | ||
| 4015 | |||
| 4016 | /* Do not open a discovered tablespace that is currently discarded. | ||
| 4017 | It will be opened properly when it is imported. */ | ||
| 4018 |
1/2✓ Branch 0 taken 91125 times.
✗ Branch 1 not taken.
|
91125 | dd_space_states dd_state = dd_tablespace_get_state_enum(&p, space_id); |
| 4019 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 91065 times.
|
91125 | if (dd_state == DD_SPACE_STATE_DISCARDED) { |
| 4020 | 60 | ++m_n_skipped; | |
| 4021 | 60 | continue; | |
| 4022 | } | ||
| 4023 | |||
| 4024 |
5/10✓ Branch 0 taken 91065 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91065 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 91064 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 91065 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
182131 | if (p.exists(se_key_value[DD_SPACE_ONLINE_ENC_PROGRESS]) && |
| 4025 |
6/12✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 91064 times.
✓ Branch 8 taken 91065 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
91066 | p.get(se_key_value[DD_SPACE_ONLINE_ENC_PROGRESS], |
| 4026 | &is_enc_in_progress)) { | ||
| 4027 | ✗ | ++m_n_errors; | |
| 4028 | ✗ | break; | |
| 4029 | } | ||
| 4030 | |||
| 4031 | /* Get the spacename for this tablespace from the DD. */ | ||
| 4032 |
4/6✓ Branch 0 taken 91065 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 91045 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 91065 times.
|
91085 | if (dd_tablespace->files().size() != 1 && |
| 4033 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | strcmp(space_name, sys_space_name) != 0) { |
| 4034 | /* Only the InnoDB system tablespace has support for | ||
| 4035 | multiple files per tablespace. For historial reasons. */ | ||
| 4036 | ✗ | ++m_n_errors; | |
| 4037 | ✗ | break; | |
| 4038 | } | ||
| 4039 | |||
| 4040 | { | ||
| 4041 |
1/2✓ Branch 0 taken 91065 times.
✗ Branch 1 not taken.
|
91065 | std::lock_guard<std::mutex> guard(m_mutex); |
| 4042 | |||
| 4043 |
6/6✓ Branch 0 taken 53493 times.
✓ Branch 1 taken 37572 times.
✓ Branch 2 taken 44012 times.
✓ Branch 3 taken 9481 times.
✓ Branch 4 taken 44012 times.
✓ Branch 5 taken 47053 times.
|
91065 | if (!dict_sys_t::is_reserved(space_id) && space_id > m_space_max_id) { |
| 4044 | /* Currently try to find the max space_id only. | ||
| 4045 | It should be able to reuse the deleted smaller ones later */ | ||
| 4046 | 44012 | m_space_max_id = space_id; | |
| 4047 | } | ||
| 4048 | 91065 | } | |
| 4049 | |||
| 4050 | /* System and temp files are tracked and opened separately. | ||
| 4051 | Consider them validated. */ | ||
| 4052 |
3/4✓ Branch 0 taken 91065 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18644 times.
✓ Branch 3 taken 72421 times.
|
91065 | if (fsp_is_system_or_temp_tablespace(space_id)) { |
| 4053 | 18644 | ++m_n_validated; | |
| 4054 | 18644 | continue; | |
| 4055 | } | ||
| 4056 | |||
| 4057 | /* Get the filename for this tablespace from the DD. */ | ||
| 4058 |
3/6✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 72421 times.
✗ Branch 5 not taken.
|
72421 | const auto file = *dd_tablespace->files().begin(); |
| 4059 |
2/4✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72421 times.
✗ Branch 3 not taken.
|
72421 | std::string dd_path{file->filename().c_str()}; |
| 4060 | 72421 | const char *filename = dd_path.c_str(); | |
| 4061 | |||
| 4062 | /* If the trunc log file is still around, this undo tablespace needs to be | ||
| 4063 | rebuilt now. */ | ||
| 4064 |
3/4✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18928 times.
✓ Branch 3 taken 53493 times.
|
72421 | if (fsp_is_undo_tablespace(space_id)) { |
| 4065 |
1/2✓ Branch 0 taken 18928 times.
✗ Branch 1 not taken.
|
18928 | mutex_enter(&undo::ddl_mutex); |
| 4066 |
1/2✓ Branch 0 taken 18928 times.
✗ Branch 1 not taken.
|
18928 | dberr_t err = srv_undo_tablespace_fixup(space_name, filename, space_id); |
| 4067 |
1/2✓ Branch 0 taken 18928 times.
✗ Branch 1 not taken.
|
18928 | mutex_exit(&undo::ddl_mutex); |
| 4068 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18928 times.
|
18928 | if (err != DB_SUCCESS) { |
| 4069 | ✗ | ib::error(ER_IB_MSG_FAILED_TO_FINISH_TRUNCATE, prefix.c_str(), | |
| 4070 | space_name); | ||
| 4071 | ✗ | continue; | |
| 4072 | } | ||
| 4073 | } | ||
| 4074 | |||
| 4075 | /* Check if IBD tablespaces exist in mem correctly. This call also adjusts | ||
| 4076 | the tablespace name for undo and general tablespace. We still need to check | ||
| 4077 | if the data files are moved. */ | ||
| 4078 |
3/4✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31403 times.
✓ Branch 3 taken 41018 times.
|
72421 | if (fil_space_exists_in_mem(space_id, space_name, false, true)) { |
| 4079 |
4/6✓ Branch 0 taken 31403 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18913 times.
✓ Branch 3 taken 12490 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 31403 times.
|
50316 | if (fsp_is_undo_tablespace(space_id) && |
| 4080 |
2/4✓ Branch 0 taken 18913 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18913 times.
|
18913 | !apply_dd_undo_state(space_id, dd_tablespace)) { |
| 4081 | /* Undo tablespaces are always opened first. But in case they have | ||
| 4082 | been moved and the DD needs to be updated, we fall thru to the location | ||
| 4083 | check below. First though, update the DD tablespace state. */ | ||
| 4084 | ✗ | ib::warn(ER_IB_MSG_FAIL_TO_SAVE_SPACE_STATE, prefix.c_str(), | |
| 4085 | space_name); | ||
| 4086 | } | ||
| 4087 | } | ||
| 4088 | |||
| 4089 | /* Check the file paths of IBD and Undo datafiles below. */ | ||
| 4090 |
6/10✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18928 times.
✓ Branch 3 taken 53493 times.
✓ Branch 4 taken 18928 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 18928 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 72421 times.
|
72421 | if (!fsp_is_ibd_tablespace(space_id) && !fsp_is_undo_tablespace(space_id)) { |
| 4091 | ✗ | continue; | |
| 4092 | } | ||
| 4093 | |||
| 4094 | /* Check if any IBD or Undo files are moved, deleted or missing. */ | ||
| 4095 | 72421 | std::string new_path; | |
| 4096 | |||
| 4097 | /* Just in case this dictionary was ported between | ||
| 4098 | Windows and POSIX. */ | ||
| 4099 | 72421 | Fil_path::normalize(dd_path); | |
| 4100 | 72421 | Fil_state state = Fil_state::MATCHES; | |
| 4101 | |||
| 4102 | 72421 | uint32_t fsp_flags = 0; | |
| 4103 |
3/6✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72421 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 72421 times.
|
72421 | if (p.get(se_key_value[DD_SPACE_FLAGS], &fsp_flags)) { |
| 4104 | /* Failed to fetch the tablespace flags. */ | ||
| 4105 | ✗ | ++m_n_errors; | |
| 4106 | ✗ | break; | |
| 4107 | } | ||
| 4108 | |||
| 4109 |
1/2✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
|
72421 | std::lock_guard<std::mutex> guard(m_mutex); |
| 4110 | |||
| 4111 |
2/4✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72421 times.
✗ Branch 3 not taken.
|
72421 | state = fil_tablespace_path_equals(space_id, space_name, fsp_flags, dd_path, |
| 4112 | &new_path); | ||
| 4113 | |||
| 4114 |
2/2✓ Branch 0 taken 72111 times.
✓ Branch 1 taken 310 times.
|
72421 | if (state == Fil_state::MATCHES) { |
| 4115 |
1/2✓ Branch 0 taken 72111 times.
✗ Branch 1 not taken.
|
72111 | new_path.assign(dd_path); |
| 4116 | } | ||
| 4117 | |||
| 4118 |
1/2✓ Branch 0 taken 72421 times.
✗ Branch 1 not taken.
|
72421 | std::string space_str(space_name); |
| 4119 | |||
| 4120 | 72421 | std::string old_space; | |
| 4121 | 72421 | bool file_name_changed = false; | |
| 4122 | 72421 | bool file_path_changed = (state == Fil_state::MOVED); | |
| 4123 | |||
| 4124 |
4/4✓ Branch 0 taken 310 times.
✓ Branch 1 taken 72111 times.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 219 times.
|
72421 | if (state == Fil_state::MATCHES || state == Fil_state::MOVED) { |
| 4125 | /* We need to update space name and table name for partitioned tables | ||
| 4126 | if letter case is different. */ | ||
| 4127 |
3/4✓ Branch 0 taken 72202 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 72093 times.
|
72202 | if (fil_update_partition_name(space_id, fsp_flags, true, space_str, |
| 4128 | new_path)) { | ||
| 4129 | 109 | file_name_changed = true; | |
| 4130 | 109 | state = Fil_state::MOVED; | |
| 4131 | } | ||
| 4132 | |||
| 4133 | /* Update DD if tablespace name is corrected. */ | ||
| 4134 |
2/2✓ Branch 0 taken 153 times.
✓ Branch 1 taken 72049 times.
|
72202 | if (space_str.compare(space_name) != 0) { |
| 4135 |
1/2✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
|
153 | old_space.assign(space_name); |
| 4136 | 153 | space_name = space_str.c_str(); | |
| 4137 | 153 | state = Fil_state::MOVED; | |
| 4138 | } | ||
| 4139 | } | ||
| 4140 | |||
| 4141 |
3/6✓ Branch 0 taken 71976 times.
✓ Branch 1 taken 219 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 226 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
72421 | switch (state) { |
| 4142 | 71976 | case Fil_state::MATCHES: | |
| 4143 | 71976 | break; | |
| 4144 | |||
| 4145 | 219 | case Fil_state::MISSING: | |
| 4146 | |||
| 4147 |
5/10✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 219 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 219 times.
✗ Branch 9 not taken.
|
438 | ib::warn(ER_IB_MSG_526) << prefix << "Tablespace " << space_id << "," |
| 4148 |
3/6✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
|
219 | << " name '" << space_name << "'," |
| 4149 |
3/6✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
|
219 | << " file '" << dd_path << "'" |
| 4150 |
1/2✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
|
219 | << " is missing!"; |
| 4151 | |||
| 4152 |
3/4✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 217 times.
|
219 | if (fsp_is_undo_tablespace(space_id)) { |
| 4153 | /* This deserves a special error message. */ | ||
| 4154 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ib::error(ER_IB_MSG_CANNOT_FIND_DD_UNDO_SPACE, space_name, filename); |
| 4155 | } | ||
| 4156 | 219 | ++m_n_missing; | |
| 4157 | 219 | continue; | |
| 4158 | |||
| 4159 | ✗ | case Fil_state::DELETED: | |
| 4160 | |||
| 4161 | ✗ | ib::warn(ER_IB_MSG_527) << prefix << "Tablespace " << space_id << "," | |
| 4162 | ✗ | << " name '" << space_name << "'," | |
| 4163 | ✗ | << " file '" << dd_path << "'" | |
| 4164 | ✗ | << " was deleted!"; | |
| 4165 | ✗ | ++m_n_deleted; | |
| 4166 | ✗ | continue; | |
| 4167 | |||
| 4168 | 226 | case Fil_state::MOVED: | |
| 4169 |
2/4✓ Branch 0 taken 226 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 226 times.
✗ Branch 3 not taken.
|
226 | fil_add_moved_space(dd_tablespace->id(), space_id, space_name, dd_path, |
| 4170 | new_path); | ||
| 4171 | 226 | ++m_n_moved; | |
| 4172 | |||
| 4173 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
|
226 | if (m_n_moved > MOVED_FILES_PRINT_THRESHOLD) { |
| 4174 | ✗ | filename = new_path.c_str(); | |
| 4175 | |||
| 4176 | ✗ | break; | |
| 4177 | } | ||
| 4178 | |||
| 4179 |
2/2✓ Branch 0 taken 153 times.
✓ Branch 1 taken 73 times.
|
226 | if (!old_space.empty()) { |
| 4180 |
1/2✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
|
153 | ib::info(ER_IB_MSG_FIL_STATE_MOVED_CORRECTED, prefix.c_str(), |
| 4181 | 153 | static_cast<unsigned long long>(dd_tablespace->id()), | |
| 4182 |
1/2✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
|
306 | static_cast<unsigned int>(space_id), old_space.c_str(), |
| 4183 | space_name); | ||
| 4184 | } | ||
| 4185 | |||
| 4186 |
2/2✓ Branch 0 taken 91 times.
✓ Branch 1 taken 135 times.
|
226 | if (file_path_changed) { |
| 4187 |
1/2✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
|
91 | ib::info(ER_IB_MSG_FIL_STATE_MOVED_CHANGED_PATH, prefix.c_str(), |
| 4188 | 91 | static_cast<unsigned long long>(dd_tablespace->id()), | |
| 4189 | ✗ | static_cast<unsigned int>(space_id), space_name, | |
| 4190 |
1/2✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
|
182 | dd_path.c_str(), new_path.c_str()); |
| 4191 | |||
| 4192 |
2/2✓ Branch 0 taken 109 times.
✓ Branch 1 taken 26 times.
|
135 | } else if (file_name_changed) { |
| 4193 |
1/2✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
|
109 | ib::info(ER_IB_MSG_FIL_STATE_MOVED_CHANGED_NAME, prefix.c_str(), |
| 4194 | 109 | static_cast<unsigned long long>(dd_tablespace->id()), | |
| 4195 | ✗ | static_cast<unsigned int>(space_id), space_name, | |
| 4196 |
1/2✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
|
218 | dd_path.c_str(), new_path.c_str()); |
| 4197 | } | ||
| 4198 | |||
| 4199 | 226 | filename = new_path.c_str(); | |
| 4200 | |||
| 4201 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
|
226 | if (m_n_moved == MOVED_FILES_PRINT_THRESHOLD) { |
| 4202 | ✗ | ib::info(ER_IB_MSG_FIL_STATE_MOVED_TOO_MANY, prefix.c_str()); | |
| 4203 | } | ||
| 4204 | 226 | break; | |
| 4205 | |||
| 4206 | ✗ | case Fil_state::RENAMED: | |
| 4207 | ✗ | break; | |
| 4208 | } | ||
| 4209 | |||
| 4210 | /* If this space is already open, we can move on to the next. */ | ||
| 4211 |
3/4✓ Branch 0 taken 72202 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31421 times.
✓ Branch 3 taken 40781 times.
|
72202 | if (nullptr != fil_space_get(space_id)) { |
| 4212 | /* Set the autoextend_size attribute for the newly opened space. */ | ||
| 4213 | 31421 | uint64_t autoextend_size{}; | |
| 4214 | |||
| 4215 |
6/10✓ Branch 0 taken 31421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31421 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21693 times.
✓ Branch 5 taken 9728 times.
✓ Branch 6 taken 21693 times.
✓ Branch 7 taken 9728 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
84535 | if (o.exists(autoextend_size_str) && |
| 4216 |
6/12✓ Branch 0 taken 21693 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21693 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21693 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21693 times.
✓ Branch 7 taken 9728 times.
✓ Branch 8 taken 31421 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
53114 | !o.get(autoextend_size_str, &autoextend_size)) { |
| 4217 |
1/2✓ Branch 0 taken 21693 times.
✗ Branch 1 not taken.
|
21693 | ut_d(dberr_t ret =) fil_set_autoextend_size(space_id, autoextend_size); |
| 4218 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21693 times.
|
21693 | ut_ad(ret == DB_SUCCESS); |
| 4219 | } | ||
| 4220 | 31421 | ++m_n_validated; | |
| 4221 | 31421 | continue; | |
| 4222 | 31421 | } | |
| 4223 | |||
| 4224 |
3/4✓ Branch 0 taken 40781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 40768 times.
|
40781 | if (fsp_is_undo_tablespace(space_id)) { |
| 4225 | /* The undo space may be open with a alternate space_id */ | ||
| 4226 | 13 | space_id_t space_num = undo::id2num(space_id); | |
| 4227 |
3/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1 times.
|
13 | if (nullptr != undo::spaces->find(space_num)) { |
| 4228 | 12 | ++m_n_validated; | |
| 4229 | 12 | continue; | |
| 4230 | } | ||
| 4231 | |||
| 4232 | /* If an undo tablespace from the DD is in an unknown location, | ||
| 4233 | it will not yet be open. */ | ||
| 4234 | 1 | undo::Tablespace undo_space(space_id); | |
| 4235 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo_space.set_space_name(space_name); |
| 4236 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo_space.set_file_name(filename); |
| 4237 | |||
| 4238 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | mutex_enter(&undo::ddl_mutex); |
| 4239 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo::spaces->x_lock(); |
| 4240 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo::use_space_id(space_id); |
| 4241 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | dberr_t err = srv_undo_tablespace_open(undo_space); |
| 4242 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo::spaces->x_unlock(); |
| 4243 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | mutex_exit(&undo::ddl_mutex); |
| 4244 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err != DB_SUCCESS) { |
| 4245 | ✗ | ib::error(ER_IB_MSG_CANNOT_FIND_DD_UNDO_SPACE, space_name, filename); | |
| 4246 | } | ||
| 4247 | 1 | ++m_n_validated; | |
| 4248 | 1 | continue; | |
| 4249 | 1 | } | |
| 4250 | |||
| 4251 | 40768 | Keyring_encryption_info keyring_encryption_info; | |
| 4252 | |||
| 4253 | /* It's safe to pass space_name in tablename charset because | ||
| 4254 | filename is already in filename charset. */ | ||
| 4255 |
4/4✓ Branch 0 taken 10613 times.
✓ Branch 1 taken 30155 times.
✓ Branch 2 taken 10602 times.
✓ Branch 3 taken 11 times.
|
40768 | bool validate = recv_needed_recovery && srv_force_recovery == 0; |
| 4256 | dberr_t err = | ||
| 4257 |
4/6✓ Branch 0 taken 30166 times.
✓ Branch 1 taken 10602 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30166 times.
✓ Branch 4 taken 40768 times.
✗ Branch 5 not taken.
|
40768 | fil_ibd_open(validate || is_enc_in_progress, FIL_TYPE_TABLESPACE, |
| 4258 | space_id, fsp_flags, space_name, filename, false, | ||
| 4259 | false, keyring_encryption_info); | ||
| 4260 | |||
| 4261 |
2/2✓ Branch 0 taken 40699 times.
✓ Branch 1 taken 69 times.
|
40768 | switch (err) { |
| 4262 | 40699 | case DB_SUCCESS: { | |
| 4263 | /* Set the autoextend_size attribute for the newly opened space. */ | ||
| 4264 | 40699 | uint64_t autoextend_size{}; | |
| 4265 | |||
| 4266 |
6/10✓ Branch 0 taken 40699 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40699 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39822 times.
✓ Branch 5 taken 877 times.
✓ Branch 6 taken 39822 times.
✓ Branch 7 taken 877 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
121220 | if (o.exists(autoextend_size_str) && |
| 4267 |
6/12✓ Branch 0 taken 39822 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39822 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39822 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 39822 times.
✓ Branch 7 taken 877 times.
✓ Branch 8 taken 40699 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
80521 | !o.get(autoextend_size_str, &autoextend_size)) { |
| 4268 | ut_d(dberr_t ret =) | ||
| 4269 |
1/2✓ Branch 0 taken 39822 times.
✗ Branch 1 not taken.
|
39822 | fil_set_autoextend_size(space_id, autoextend_size); |
| 4270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39822 times.
|
39822 | ut_ad(ret == DB_SUCCESS); |
| 4271 | } | ||
| 4272 | 40699 | ++m_n_validated; | |
| 4273 | 40699 | break; | |
| 4274 | } | ||
| 4275 | 69 | case DB_CANNOT_OPEN_FILE: | |
| 4276 | case DB_WRONG_FILE_NAME: | ||
| 4277 | default: | ||
| 4278 |
5/10✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 69 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 69 times.
✗ Branch 9 not taken.
|
69 | ib::info(ER_IB_MSG_530) << prefix << "Tablespace " << space_id << "," |
| 4279 |
3/6✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
|
69 | << " name '" << space_name << "'," |
| 4280 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | << " unable to open file" |
| 4281 |
5/10✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 69 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 69 times.
✗ Branch 9 not taken.
|
69 | << " '" << filename << "' - " << ut_strerr(err); |
| 4282 | 69 | ++m_n_missing; | |
| 4283 | } | ||
| 4284 |
10/12✓ Branch 0 taken 40768 times.
✓ Branch 1 taken 31653 times.
✓ Branch 2 taken 40768 times.
✓ Branch 3 taken 31653 times.
✓ Branch 4 taken 40768 times.
✓ Branch 5 taken 31653 times.
✓ Branch 6 taken 40768 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 31653 times.
✓ Branch 9 taken 40768 times.
✓ Branch 10 taken 31653 times.
✗ Branch 11 not taken.
|
199033 | } |
| 4285 | |||
| 4286 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | mem_heap_free(heap); |
| 4287 | 9331 | } | |
| 4288 | |||
| 4289 | 9331 | dberr_t Validate_files::validate(const DD_tablespaces &tablespaces) { | |
| 4290 | 9331 | m_n_to_check = tablespaces.size(); | |
| 4291 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | m_n_threads = fil_get_scan_threads(m_n_to_check); |
| 4292 | 9331 | m_start_time = std::chrono::steady_clock::now(); | |
| 4293 | |||
| 4294 |
4/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9320 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 2 times.
|
9331 | if (!srv_validate_tablespace_paths && !recv_needed_recovery) { |
| 4295 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | ib::info(ER_IB_TABLESPACE_PATH_VALIDATION_SKIPPED); |
| 4296 | } | ||
| 4297 | |||
| 4298 | using std::placeholders::_1; | ||
| 4299 | using std::placeholders::_2; | ||
| 4300 | using std::placeholders::_3; | ||
| 4301 | |||
| 4302 | std::function<void(const Validate_files::Const_iter &, | ||
| 4303 | const Validate_files::Const_iter &, size_t)> | ||
| 4304 |
2/4✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
|
9331 | check = std::bind(&Validate_files::check, this, _1, _2, _3); |
| 4305 | |||
| 4306 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | par_for(PFS_NOT_INSTRUMENTED, tablespaces, m_n_threads, check); |
| 4307 | |||
| 4308 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | std::ostringstream msg; |
| 4309 |
2/4✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
|
9331 | msg << "Scanned " << m_n_to_check << " tablespaces." |
| 4310 |
4/8✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9331 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9331 times.
✗ Branch 7 not taken.
|
18662 | << " Validated " << m_n_validated.load() << "."; |
| 4311 | |||
| 4312 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 9307 times.
|
18662 | if (m_n_skipped.load() > 0) { |
| 4313 |
3/6✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
48 | msg << " Skipped " << m_n_skipped.load() << "."; |
| 4314 | } | ||
| 4315 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9303 times.
|
18662 | if (m_n_moved.load() > 0) { |
| 4316 |
3/6✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
|
56 | msg << " Found " << m_n_moved.load() << " moved."; |
| 4317 | } | ||
| 4318 |
2/2✓ Branch 0 taken 107 times.
✓ Branch 1 taken 9224 times.
|
18662 | if (m_n_missing.load() > 0) { |
| 4319 |
3/6✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 107 times.
✗ Branch 5 not taken.
|
214 | msg << " Found " << m_n_missing.load() << " missing."; |
| 4320 | } | ||
| 4321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
|
18662 | if (m_n_deleted.load() > 0) { |
| 4322 | ✗ | msg << " Found " << m_n_deleted.load() << " deleted."; | |
| 4323 | } | ||
| 4324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
|
18662 | if (m_n_errors.load() > 0) { |
| 4325 | ✗ | msg << " Encountered " << m_n_errors.load() << " errors."; | |
| 4326 | } | ||
| 4327 |
3/6✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9331 times.
✗ Branch 5 not taken.
|
9331 | ib::info(ER_IB_MSG_531) << msg.str(); |
| 4328 | |||
| 4329 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
|
9331 | if (failed()) { |
| 4330 | ✗ | return (DB_ERROR); | |
| 4331 | } | ||
| 4332 | |||
| 4333 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | fil_set_max_space_id_if_bigger(get_space_max_id()); |
| 4334 | |||
| 4335 |
2/2✓ Branch 0 taken 9320 times.
✓ Branch 1 taken 11 times.
|
9331 | if (srv_validate_tablespace_paths) { |
| 4336 | 9320 | clone_sys->set_space_initialized(); | |
| 4337 | } | ||
| 4338 | |||
| 4339 | 9331 | return (DB_SUCCESS); | |
| 4340 | 9331 | } | |
| 4341 | |||
| 4342 | /** Discover all InnoDB tablespaces. | ||
| 4343 | @param[in,out] thd thread handle | ||
| 4344 | @retval true on error | ||
| 4345 | @retval false on success */ | ||
| 4346 | 9331 | [[nodiscard]] static bool boot_tablespaces(THD *thd) { | |
| 4347 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | auto dc = dd::get_dd_client(thd); |
| 4348 | |||
| 4349 | using DD_tablespaces = std::vector<const dd::Tablespace *>; | ||
| 4350 | using Releaser = dd::cache::Dictionary_client::Auto_releaser; | ||
| 4351 | |||
| 4352 | 9331 | DD_tablespaces tablespaces; | |
| 4353 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | Releaser releaser(dc); |
| 4354 | |||
| 4355 | /* Initialize the max space_id from sys header */ | ||
| 4356 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | dict_sys_mutex_enter(); |
| 4357 | |||
| 4358 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | mtr_t mtr; |
| 4359 | |||
| 4360 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | mtr_start(&mtr); |
| 4361 | |||
| 4362 |
2/4✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
|
9331 | space_id_t space_max_id = mtr_read_ulint( |
| 4363 | dict_hdr_get(&mtr) + DICT_HDR_MAX_SPACE_ID, MLOG_4BYTES, &mtr); | ||
| 4364 | |||
| 4365 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | mtr_commit(&mtr); |
| 4366 | |||
| 4367 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | fil_set_max_space_id_if_bigger(space_max_id); |
| 4368 | |||
| 4369 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | dict_sys_mutex_exit(); |
| 4370 | |||
| 4371 |
2/4✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
|
9331 | ib::info(ER_IB_MSG_532) << "Reading DD tablespace files"; |
| 4372 | |||
| 4373 |
2/4✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9331 times.
|
9331 | if (dc->fetch_global_components(&tablespaces)) { |
| 4374 | /* Failed to fetch the tablespaces from the DD. */ | ||
| 4375 | |||
| 4376 | ✗ | return (DD_FAILURE); | |
| 4377 | } | ||
| 4378 | |||
| 4379 | 9331 | Validate_files validator; | |
| 4380 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | dberr_t err = validator.validate(tablespaces); |
| 4381 | |||
| 4382 |
1/2✓ Branch 0 taken 9331 times.
✗ Branch 1 not taken.
|
9331 | return (err == DB_SUCCESS ? DD_SUCCESS : DD_FAILURE); |
| 4383 | 9331 | } | |
| 4384 | |||
| 4385 | /** Create metadata for a predefined tablespace at server initialization. | ||
| 4386 | @param[in,out] dd_client data dictionary client | ||
| 4387 | @param[in] space_id InnoDB tablespace ID | ||
| 4388 | @param[in] flags tablespace flags | ||
| 4389 | @param[in] name tablespace name | ||
| 4390 | @param[in] filename tablespace file name | ||
| 4391 | @retval false on success | ||
| 4392 | @retval true on failure */ | ||
| 4393 | 849 | static bool predefine_tablespace(dd::cache::Dictionary_client *dd_client, | |
| 4394 | space_id_t space_id, uint32_t flags, | ||
| 4395 | const char *name, const char *filename) { | ||
| 4396 | dd::Object_id dd_space_id; | ||
| 4397 | |||
| 4398 |
1/2✓ Branch 0 taken 849 times.
✗ Branch 1 not taken.
|
849 | return (dd_create_tablespace(dd_client, name, space_id, flags, filename, |
| 4399 | 1698 | false, dd_space_id)); | |
| 4400 | } | ||
| 4401 | |||
| 4402 | /** Check if InnoDB is in a mode where the data dictionary is read-only. | ||
| 4403 | @return true if srv_read_only_mode is true or if srv_force_recovery > 0 */ | ||
| 4404 | 97477 | static bool innobase_is_dict_readonly() { | |
| 4405 |
1/2✓ Branch 0 taken 97477 times.
✗ Branch 1 not taken.
|
97477 | DBUG_TRACE; |
| 4406 |
4/4✓ Branch 0 taken 97202 times.
✓ Branch 1 taken 275 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 97090 times.
|
194954 | return srv_read_only_mode || srv_force_recovery > 0; |
| 4407 | 97477 | } | |
| 4408 | |||
| 4409 | #ifndef UNIV_HOTBACKUP | ||
| 4410 | /** Update metadata for innodb_temporary tablespace at server startup. | ||
| 4411 | This information is used by the information_schema.files to show the | ||
| 4412 | filename for the temporary tablespace innodb_temporary. | ||
| 4413 | @param[in,out] thd THD | ||
| 4414 | @retval false on success | ||
| 4415 | @retval true on failure */ | ||
| 4416 | 9614 | static bool update_innodb_temporary_metadata(THD *thd) { | |
| 4417 |
3/4✓ Branch 0 taken 9614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 9557 times.
|
9614 | if (innobase_is_dict_readonly()) { |
| 4418 | /* Metadata cannot be updated if the server is started in read_only | ||
| 4419 | mode. This means that the values for innodb_temp_data_file_path and | ||
| 4420 | file_name in information_schema.files will not be in same. */ | ||
| 4421 |
8/16✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 57 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 57 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 57 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 57 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 57 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 57 times.
✗ Branch 15 not taken.
|
57 | LogErr(WARNING_LEVEL, ER_SKIP_UPDATING_METADATA_IN_SE_RO_MODE, |
| 4422 | "information_schema"); | ||
| 4423 | 57 | return false; | |
| 4424 | } | ||
| 4425 | |||
| 4426 | /* Get the filename from srv_tmp_space */ | ||
| 4427 |
1/2✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
|
9557 | auto fpath = srv_tmp_space.first_datafile()->filepath(); |
| 4428 | 9557 | auto &dc = *thd->dd_client(); | |
| 4429 |
1/2✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
|
9557 | dd::cache::Dictionary_client::Auto_releaser releaser(&dc); |
| 4430 |
1/2✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
|
9557 | const dd::String_type tbsp_name{dict_sys_t::s_temp_space_name}; |
| 4431 | 9557 | dd::Tablespace *tmp_tbsp{nullptr}; | |
| 4432 | |||
| 4433 |
3/6✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9557 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9557 times.
✗ Branch 5 not taken.
|
19114 | if (!dc.acquire_for_modification<dd::Tablespace>(tbsp_name, &tmp_tbsp) && |
| 4434 |
1/2✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
|
9557 | tmp_tbsp != nullptr) { |
| 4435 |
2/4✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9557 times.
|
9557 | ut_ad(tmp_tbsp->files().size() == 1); |
| 4436 | |||
| 4437 | /* Get the tablespace file for innodb_temporary tablespace. */ | ||
| 4438 | dd::Tablespace_file *dd_file = | ||
| 4439 |
3/6✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9557 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9557 times.
✗ Branch 5 not taken.
|
9557 | const_cast<dd::Tablespace_file *>(*(tmp_tbsp->files().begin())); |
| 4440 | |||
| 4441 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9557 times.
|
9557 | ut_ad(dd_file); |
| 4442 | |||
| 4443 |
2/4✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9557 times.
✗ Branch 3 not taken.
|
9557 | dd_file->set_filename(fpath); |
| 4444 | |||
| 4445 |
2/4✓ Branch 0 taken 9557 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9557 times.
|
9557 | if (dc.update(tmp_tbsp)) { |
| 4446 | /* Unable to update the metadata. */ | ||
| 4447 | ✗ | ut_d(ut_error); | |
| 4448 | ut_o(return true); | ||
| 4449 | } | ||
| 4450 | } else { | ||
| 4451 | /* Unable to acquire innodb_temporary tablespace for modification. */ | ||
| 4452 | ✗ | ut_d(ut_error); | |
| 4453 | ut_o(return true); | ||
| 4454 | } | ||
| 4455 | 9557 | return false; | |
| 4456 | 9557 | } | |
| 4457 | #endif /* !UNIV_HOTBACKUP */ | ||
| 4458 | |||
| 4459 | /** Predefine the undo tablespace metadata at server initialization. | ||
| 4460 | @param[in,out] dd_client data dictionary client | ||
| 4461 | @retval false on success | ||
| 4462 | @retval true on failure */ | ||
| 4463 | 283 | static bool predefine_undo_tablespaces( | |
| 4464 | dd::cache::Dictionary_client *dd_client) { | ||
| 4465 | /** Undo tablespaces use a reserved range of tablespace ID. */ | ||
| 4466 |
2/2✓ Branch 0 taken 566 times.
✓ Branch 1 taken 283 times.
|
849 | for (auto undo_space : undo::spaces->m_spaces) { |
| 4467 |
1/2✓ Branch 0 taken 566 times.
✗ Branch 1 not taken.
|
566 | uint32_t flags = fsp_flags_init(univ_page_size, false, false, false, false); |
| 4468 | |||
| 4469 |
2/4✓ Branch 0 taken 566 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 566 times.
|
566 | if (predefine_tablespace(dd_client, undo_space->id(), flags, |
| 4470 | 566 | undo_space->space_name(), | |
| 4471 |
2/4✓ Branch 0 taken 566 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 566 times.
✗ Branch 3 not taken.
|
566 | undo_space->file_name())) { |
| 4472 | ✗ | return (true); | |
| 4473 | } | ||
| 4474 | } | ||
| 4475 | |||
| 4476 | 283 | return (false); | |
| 4477 | } | ||
| 4478 | |||
| 4479 | /** Invalidate an entry or entries for partitoined table from the dict cache. | ||
| 4480 | @param[in] schema_name Schema name | ||
| 4481 | @param[in] table_name Table name */ | ||
| 4482 | 278605 | static void innobase_dict_cache_reset(const char *schema_name, | |
| 4483 | const char *table_name) { | ||
| 4484 | char name[FN_REFLEN]; | ||
| 4485 | 278605 | snprintf(name, sizeof name, "%s/%s", schema_name, table_name); | |
| 4486 | |||
| 4487 |
1/2✓ Branch 0 taken 278605 times.
✗ Branch 1 not taken.
|
278605 | dict_sys_mutex_enter(); |
| 4488 | |||
| 4489 |
1/2✓ Branch 0 taken 278605 times.
✗ Branch 1 not taken.
|
278605 | dict_table_t *table = dict_table_check_if_in_cache_low(name); |
| 4490 | |||
| 4491 |
2/2✓ Branch 0 taken 163452 times.
✓ Branch 1 taken 115153 times.
|
278605 | if (table != nullptr) { |
| 4492 |
1/2✓ Branch 0 taken 163452 times.
✗ Branch 1 not taken.
|
163452 | btr_drop_ahi_for_table(table); |
| 4493 |
1/2✓ Branch 0 taken 163452 times.
✗ Branch 1 not taken.
|
163452 | dict_table_remove_from_cache(table); |
| 4494 |
2/2✓ Branch 0 taken 2791 times.
✓ Branch 1 taken 112362 times.
|
115153 | } else if (strcmp(schema_name, "mysql") != 0) { |
| 4495 |
1/2✓ Branch 0 taken 2791 times.
✗ Branch 1 not taken.
|
2791 | dict_partitioned_table_remove_from_cache(name); |
| 4496 | } | ||
| 4497 | |||
| 4498 |
1/2✓ Branch 0 taken 278605 times.
✗ Branch 1 not taken.
|
278605 | dict_sys_mutex_exit(); |
| 4499 | 278605 | } | |
| 4500 | |||
| 4501 | /** Invalidate user table dict cache after Replication Plugin recovers. Table | ||
| 4502 | definition could be different with XA commit/rollback of DDL operations */ | ||
| 4503 | 9493 | static void innobase_dict_cache_reset_tables_and_tablespaces() { | |
| 4504 | 9493 | dict_sys_mutex_enter(); | |
| 4505 | |||
| 4506 | /* There should be no DDL/DML activity at this stage, so access | ||
| 4507 | the LRU chain without mutex. We only invalidates the table | ||
| 4508 | in LRU list */ | ||
| 4509 |
7/12✓ Branch 0 taken 9493 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9493 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9493 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 186211 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 195704 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 186211 times.
✓ Branch 11 taken 9493 times.
|
195704 | for (auto table : dict_sys->table_LRU.removable()) { |
| 4510 | /* Make sure table->is_dd_table is set */ | ||
| 4511 | |||
| 4512 | 186211 | std::string db_str; | |
| 4513 | 186211 | std::string tbl_str; | |
| 4514 |
2/4✓ Branch 0 taken 186211 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 186211 times.
✗ Branch 3 not taken.
|
186211 | dict_name::get_table(table->name.m_name, db_str, tbl_str); |
| 4515 | |||
| 4516 | /* TODO: Remove follow if we have better way to identify | ||
| 4517 | DD "system table" */ | ||
| 4518 |
1/2✓ Branch 0 taken 20930 times.
✗ Branch 1 not taken.
|
207141 | if (db_str.compare("mysql") == 0 || table->is_dd_table || |
| 4519 |
9/10✓ Branch 0 taken 20930 times.
✓ Branch 1 taken 165281 times.
✓ Branch 2 taken 20930 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20929 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1315 times.
✓ Branch 7 taken 19614 times.
✓ Branch 8 taken 166597 times.
✓ Branch 9 taken 19614 times.
|
228070 | table->is_corrupted() || |
| 4520 | 20929 | DICT_TF2_FLAG_IS_SET(table, DICT_TF2_RESURRECT_PREPARED)) { | |
| 4521 | 166597 | continue; | |
| 4522 | } | ||
| 4523 | |||
| 4524 |
1/2✓ Branch 0 taken 19614 times.
✗ Branch 1 not taken.
|
19614 | table->acquire(); |
| 4525 |
1/2✓ Branch 0 taken 19614 times.
✗ Branch 1 not taken.
|
19614 | btr_drop_ahi_for_table(table); |
| 4526 |
1/2✓ Branch 0 taken 19614 times.
✗ Branch 1 not taken.
|
19614 | dd_table_close(table, nullptr, nullptr, true); |
| 4527 | |||
| 4528 |
1/2✓ Branch 0 taken 19614 times.
✗ Branch 1 not taken.
|
19614 | dict_table_remove_from_cache(table); |
| 4529 |
4/4✓ Branch 0 taken 19614 times.
✓ Branch 1 taken 166597 times.
✓ Branch 2 taken 19614 times.
✓ Branch 3 taken 166597 times.
|
352808 | } |
| 4530 | 9493 | dict_sys_mutex_exit(); | |
| 4531 | 9493 | } | |
| 4532 | |||
| 4533 | /** Perform high-level recovery in InnoDB as part of initializing the | ||
| 4534 | data dictionary. | ||
| 4535 | @param[in] dict_recovery_mode How to do recovery | ||
| 4536 | @param[in] version Target DD version if a new | ||
| 4537 | server is being installed. | ||
| 4538 | Actual DD version if restarting | ||
| 4539 | an existing server. | ||
| 4540 | @retval true An error occurred. | ||
| 4541 | @retval false Success - no errors. */ | ||
| 4542 | 9897 | static bool innobase_dict_recover(dict_recovery_mode_t dict_recovery_mode, | |
| 4543 | uint version [[maybe_unused]]) { | ||
| 4544 | 9897 | THD *thd = current_thd; | |
| 4545 | |||
| 4546 |
2/3✓ Branch 0 taken 283 times.
✓ Branch 1 taken 9614 times.
✗ Branch 2 not taken.
|
9897 | switch (dict_recovery_mode) { |
| 4547 | 283 | case DICT_RECOVERY_INITIALIZE_TABLESPACES: | |
| 4548 | 283 | break; | |
| 4549 | 9614 | case DICT_RECOVERY_RESTART_SERVER: | |
| 4550 | [[fallthrough]]; | ||
| 4551 | case DICT_RECOVERY_INITIALIZE_SERVER: | ||
| 4552 |
2/2✓ Branch 0 taken 8097 times.
✓ Branch 1 taken 1517 times.
|
9614 | if (dict_sys->dynamic_metadata == nullptr) { |
| 4553 | 16194 | dict_sys->dynamic_metadata = | |
| 4554 | 8097 | dd_table_open_on_name(thd, nullptr, "mysql/innodb_dynamic_metadata", | |
| 4555 | false, DICT_ERR_IGNORE_NONE); | ||
| 4556 | 16194 | dict_persist->table_buffer = | |
| 4557 | 8097 | ut::new_withkey<DDTableBuffer>(UT_NEW_THIS_FILE_PSI_KEY); | |
| 4558 | } | ||
| 4559 | |||
| 4560 | 19228 | dict_sys->table_stats = | |
| 4561 | 9614 | dd_table_open_on_name(thd, nullptr, "mysql/innodb_table_stats", false, | |
| 4562 | DICT_ERR_IGNORE_NONE); | ||
| 4563 | 19228 | dict_sys->index_stats = | |
| 4564 | 9614 | dd_table_open_on_name(thd, nullptr, "mysql/innodb_index_stats", false, | |
| 4565 | DICT_ERR_IGNORE_NONE); | ||
| 4566 | 9614 | dict_sys->ddl_log = dd_table_open_on_name( | |
| 4567 | thd, nullptr, "mysql/innodb_ddl_log", false, DICT_ERR_IGNORE_NONE); | ||
| 4568 | 9614 | log_ddl = ut::new_withkey<Log_DDL>(UT_NEW_THIS_FILE_PSI_KEY); | |
| 4569 | } | ||
| 4570 | |||
| 4571 |
3/4✓ Branch 0 taken 283 times.
✓ Branch 1 taken 283 times.
✓ Branch 2 taken 9331 times.
✗ Branch 3 not taken.
|
9897 | switch (dict_recovery_mode) { |
| 4572 | 283 | case DICT_RECOVERY_INITIALIZE_SERVER: | |
| 4573 | 283 | return (false); | |
| 4574 | 283 | case DICT_RECOVERY_INITIALIZE_TABLESPACES: { | |
| 4575 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 4576 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 4577 | |||
| 4578 |
2/4✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 283 times.
|
283 | if (predefine_tablespace(client, dict_sys_t::s_temp_space_id, |
| 4579 | srv_tmp_space.flags(), | ||
| 4580 | dict_sys_t::s_temp_space_name, | ||
| 4581 | dict_sys_t::s_temp_space_file_name)) { | ||
| 4582 | ✗ | return (DD_FAILURE); | |
| 4583 | } | ||
| 4584 | |||
| 4585 |
2/4✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 283 times.
|
283 | if (predefine_undo_tablespaces(client)) { |
| 4586 | ✗ | return (DD_FAILURE); | |
| 4587 | } | ||
| 4588 | |||
| 4589 | 283 | break; | |
| 4590 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 283 times.
|
283 | } |
| 4591 | 9331 | case DICT_RECOVERY_RESTART_SERVER: | |
| 4592 | /* Traverse dd::tablespaces and apply/validate this metadata. */ | ||
| 4593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
|
9331 | if (boot_tablespaces(thd)) { |
| 4594 | ✗ | return (true); | |
| 4595 | } | ||
| 4596 | |||
| 4597 | #ifndef UNIV_HOTBACKUP | ||
| 4598 | /* For all tablespaces for which tablespace key is to be reencrypt, | ||
| 4599 | do it now. */ | ||
| 4600 | 9331 | fil_encryption_reencrypt(Encryption::s_tablespaces_to_reencrypt); | |
| 4601 | #endif /* !UNIV_HOTBACKUP */ | ||
| 4602 | |||
| 4603 | /* We might need to fix tables for CSV and MyISAM SE */ | ||
| 4604 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9331 times.
|
9331 | if (fix_cloned_tables(thd)) { |
| 4605 | ✗ | return (true); | |
| 4606 | } | ||
| 4607 | |||
| 4608 | 9331 | srv_dict_recover_on_restart(); | |
| 4609 | } | ||
| 4610 | |||
| 4611 | 9614 | srv_start_threads(dict_recovery_mode != DICT_RECOVERY_RESTART_SERVER); | |
| 4612 | |||
| 4613 | #ifndef UNIV_HOTBACKUP | ||
| 4614 | /* Update the metadata for innodb_temporary tablespace to reflect | ||
| 4615 | the correct filename. */ | ||
| 4616 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9614 times.
|
9614 | if (update_innodb_temporary_metadata(thd)) { |
| 4617 | ✗ | return true; | |
| 4618 | } | ||
| 4619 | #endif /* !UNIV_HOTBACKUP */ | ||
| 4620 | |||
| 4621 | 9614 | return (fil_open_for_business(srv_read_only_mode) != DB_SUCCESS); | |
| 4622 | } | ||
| 4623 | |||
| 4624 | /** DDL crash recovery: process the records recovered from "log_ddl" table */ | ||
| 4625 | 9493 | static void innobase_post_recover() { | |
| 4626 |
2/2✓ Branch 0 taken 9477 times.
✓ Branch 1 taken 16 times.
|
9493 | if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { |
| 4627 |
2/4✓ Branch 0 taken 9477 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9477 times.
|
9477 | DBUG_EXECUTE_IF("DDL_Log_remove_inject_startup_error_2", |
| 4628 | srv_inject_too_many_concurrent_trxs = true;); | ||
| 4629 | |||
| 4630 |
1/2✓ Branch 0 taken 9477 times.
✗ Branch 1 not taken.
|
9477 | dberr_t err = log_ddl->recover(); |
| 4631 | |||
| 4632 | /* Abort post recovery startup if this is not successful. */ | ||
| 4633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9477 times.
|
9477 | if (err != DB_SUCCESS) { |
| 4634 | ✗ | ib::fatal(UT_LOCATION_HERE, ER_IB_MSG_POST_RECOVER_DDL_LOG_RECOVER); | |
| 4635 | } | ||
| 4636 | } | ||
| 4637 | |||
| 4638 |
1/2✓ Branch 0 taken 9493 times.
✗ Branch 1 not taken.
|
9493 | fil_free_scanned_files(); |
| 4639 | |||
| 4640 | /* If undo tablespaces are to be encrypted, encrypt them now */ | ||
| 4641 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 9453 times.
|
9493 | if (srv_undo_log_encrypt) { |
| 4642 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | ut_ad(Encryption::check_keyring()); |
| 4643 | |||
| 4644 | /* There would be at least 2 UNDO tablespaces */ | ||
| 4645 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | ut_ad(undo::spaces->size() >= FSP_IMPLICIT_UNDO_TABLESPACES); |
| 4646 | |||
| 4647 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | if (srv_read_only_mode) { |
| 4648 | ✗ | ib::error(ER_IB_MSG_1051); | |
| 4649 | ✗ | srv_undo_log_encrypt = false; | |
| 4650 | } else { | ||
| 4651 | /* Enable encryption for UNDO tablespaces */ | ||
| 4652 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | mutex_enter(&undo::ddl_mutex); |
| 4653 |
2/4✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
|
40 | if (srv_enable_undo_encryption(nullptr)) { |
| 4654 | ✗ | srv_undo_log_encrypt = false; | |
| 4655 | ✗ | ut_d(ut_error); | |
| 4656 | } | ||
| 4657 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | mutex_exit(&undo::ddl_mutex); |
| 4658 | |||
| 4659 | /* We have to ensure that the first page of the undo tablespaces gets | ||
| 4660 | flushed to disk. Otherwise during recovery, since we read the first | ||
| 4661 | page without applying the redo logs, it will be determined that | ||
| 4662 | encryption is off. */ | ||
| 4663 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | buf_flush_sync_all_buf_pools(); |
| 4664 | } | ||
| 4665 | } | ||
| 4666 | |||
| 4667 | /* If redo log is to be encrypted, encrypt it now */ | ||
| 4668 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 9450 times.
|
9493 | if (srv_redo_log_encrypt) { |
| 4669 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | ut_ad(Encryption::check_keyring()); |
| 4670 | |||
| 4671 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | if (srv_read_only_mode) { |
| 4672 | ✗ | ib::error(ER_IB_MSG_LOG_FILES_CANNOT_ENCRYPT_IN_READ_ONLY); | |
| 4673 | ✗ | srv_redo_log_encrypt = false; | |
| 4674 | } else { | ||
| 4675 | /* Enable encryption for REDO log */ | ||
| 4676 |
2/4✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43 times.
|
43 | if (srv_enable_redo_encryption()) { |
| 4677 | ✗ | srv_redo_log_encrypt = false; | |
| 4678 | ✗ | ut_d(ut_error); | |
| 4679 | } | ||
| 4680 | } | ||
| 4681 | } | ||
| 4682 | |||
| 4683 |
4/4✓ Branch 0 taken 9455 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9445 times.
|
9493 | if (srv_read_only_mode || srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) { |
| 4684 | 48 | purge_sys->state = PURGE_STATE_DISABLED; | |
| 4685 | 48 | return; | |
| 4686 | } | ||
| 4687 | |||
| 4688 |
1/2✓ Branch 0 taken 9445 times.
✗ Branch 1 not taken.
|
9445 | Auto_THD thd; |
| 4689 |
2/4✓ Branch 0 taken 9445 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9445 times.
|
9445 | if (dd_tablespace_update_cache(thd.thd)) { |
| 4690 | ✗ | ut_d(ut_error); | |
| 4691 | } | ||
| 4692 | |||
| 4693 |
1/2✓ Branch 0 taken 9443 times.
✗ Branch 1 not taken.
|
9445 | srv_start_threads_after_ddl_recovery(); |
| 4694 | |||
| 4695 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9443 times.
|
9443 | ut_a(innodb_inited); |
| 4696 | |||
| 4697 |
2/2✓ Branch 0 taken 9241 times.
✓ Branch 1 taken 202 times.
|
9443 | if (!opt_initialize) { |
| 4698 |
2/4✓ Branch 0 taken 9233 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9233 times.
|
9241 | if (!log_pfs_create_tables()) { |
| 4699 | ✗ | ib::warn(ER_IB_MSG_LOG_PFS_CREATE_TABLES_FAILED); | |
| 4700 | } | ||
| 4701 | } | ||
| 4702 | 9435 | } | |
| 4703 | |||
| 4704 | /** | ||
| 4705 | Get the server version id stored in the header of the | ||
| 4706 | dictionary tablespace. | ||
| 4707 | |||
| 4708 | @param [out] version Version number from the DD | ||
| 4709 | tablespace header. | ||
| 4710 | |||
| 4711 | @retval Operation outcome, false if no error, otherwise true. | ||
| 4712 | */ | ||
| 4713 | 19135 | static bool innobase_dict_get_server_version(uint *version) { | |
| 4714 | 19135 | return (fsp_header_dict_get_server_version(version)); | |
| 4715 | } | ||
| 4716 | |||
| 4717 | /** | ||
| 4718 | Store the current server version number into the | ||
| 4719 | header of the dictionary tablespace. | ||
| 4720 | |||
| 4721 | @retval Operation outcome, false if no error, otherwise true. | ||
| 4722 | */ | ||
| 4723 | 167 | static bool innobase_dict_set_server_version() { | |
| 4724 | /* Update the server version number, but leave the space version unchanged */ | ||
| 4725 | 167 | return (upgrade_space_version(dict_sys_t::s_dict_space_id, true)); | |
| 4726 | } | ||
| 4727 | |||
| 4728 | /** Start page tracking. | ||
| 4729 | @param[out] start_id LSN indicating when the tracking was started | ||
| 4730 | @return Operation status. | ||
| 4731 | @retval 0 Success | ||
| 4732 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4733 | ✗ | static int innobase_page_track_start(uint64_t *start_id) { | |
| 4734 | ✗ | if (srv_read_only_mode) { | |
| 4735 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4736 | ✗ | return ER_READ_ONLY_MODE; | |
| 4737 | } | ||
| 4738 | |||
| 4739 | ✗ | Page_Arch_Client_Ctx *ctx = arch_page_sys->get_sys_client(); | |
| 4740 | |||
| 4741 | ✗ | int err = ctx->start(false, start_id); | |
| 4742 | |||
| 4743 | ✗ | return (err); | |
| 4744 | } | ||
| 4745 | |||
| 4746 | /** Stop page tracking. | ||
| 4747 | @param[out] stop_id Stop LSN indicating when the tracking was stopped | ||
| 4748 | @return Operation status. | ||
| 4749 | @retval 0 Success | ||
| 4750 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4751 | ✗ | static int innobase_page_track_stop(uint64_t *stop_id) { | |
| 4752 | ✗ | if (srv_read_only_mode) { | |
| 4753 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4754 | ✗ | return ER_READ_ONLY_MODE; | |
| 4755 | } | ||
| 4756 | |||
| 4757 | ✗ | Page_Arch_Client_Ctx *ctx = arch_page_sys->get_sys_client(); | |
| 4758 | |||
| 4759 | ✗ | int err = ctx->stop(stop_id); | |
| 4760 | |||
| 4761 | ✗ | return (err); | |
| 4762 | } | ||
| 4763 | |||
| 4764 | /** Purge page tracking data. | ||
| 4765 | @param[in,out] purge_id Purge LSN initially indicating till where the data | ||
| 4766 | needs to be purged and finally updated to until where it was actually purged | ||
| 4767 | @return Operation status. | ||
| 4768 | @retval 0 Success | ||
| 4769 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4770 | ✗ | static int innobase_page_track_purge(uint64_t *purge_id) { | |
| 4771 | ✗ | if (srv_read_only_mode) { | |
| 4772 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4773 | ✗ | return ER_READ_ONLY_MODE; | |
| 4774 | } | ||
| 4775 | |||
| 4776 | ✗ | auto err = arch_page_sys->purge(purge_id); | |
| 4777 | |||
| 4778 | ✗ | return (err); | |
| 4779 | } | ||
| 4780 | |||
| 4781 | /** Fetch tracked pages. | ||
| 4782 | @param[in] cbk_func callback function return page IDs | ||
| 4783 | @param[in] cbk_ctx caller's context for callback | ||
| 4784 | @param[in,out] start_id SE specific sequence number [LSN for Innodb] from | ||
| 4785 | where the pages tracked would be returned. | ||
| 4786 | @note The range might get expanded and the actual start_id used for the | ||
| 4787 | querying will be updated. | ||
| 4788 | @param[in,out] stop_id SE specific sequence number [LSN for Innodb] | ||
| 4789 | until where the pages tracked would be returned. | ||
| 4790 | @note The range might get expanded and the actual stop_id used for the | ||
| 4791 | querying will be updated. | ||
| 4792 | @param[out] buffer allocated buffer to copy page IDs | ||
| 4793 | @param[in] buffer_len length of buffer in bytes | ||
| 4794 | @return Operation status. | ||
| 4795 | @retval 0 Success | ||
| 4796 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4797 | ✗ | static int innobase_page_track_get_page_ids(Page_Track_Callback cbk_func, | |
| 4798 | void *cbk_ctx, uint64_t *start_id, | ||
| 4799 | uint64_t *stop_id, | ||
| 4800 | unsigned char *buffer, | ||
| 4801 | size_t buffer_len) { | ||
| 4802 | ✗ | if (srv_read_only_mode) { | |
| 4803 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4804 | ✗ | return ER_READ_ONLY_MODE; | |
| 4805 | } | ||
| 4806 | |||
| 4807 | auto err = | ||
| 4808 | ✗ | arch_page_sys->get_pages(nullptr, cbk_func, cbk_ctx, *start_id, *stop_id, | |
| 4809 | buffer, static_cast<uint>(buffer_len)); | ||
| 4810 | |||
| 4811 | ✗ | if (err != 0) { | |
| 4812 | ✗ | DBUG_PRINT("page_archiver", ("Fetch Pages")); | |
| 4813 | ✗ | DBUG_PRINT("page_archiver", ("Can't fetch pages")); | |
| 4814 | } | ||
| 4815 | |||
| 4816 | ✗ | return (err); | |
| 4817 | } | ||
| 4818 | |||
| 4819 | /** Fetch approximate number of tracked pages in the given range. | ||
| 4820 | @param[in,out] start_id SE specific sequence number [LSN for Innodb] from | ||
| 4821 | where the pages tracked would be returned. | ||
| 4822 | @note the range might get expanded and the actual start_id used for the | ||
| 4823 | querying will be updated. | ||
| 4824 | @param[in,out] stop_id SE specific sequence number [LSN for Innodb] | ||
| 4825 | until where the pages tracked would be returned. | ||
| 4826 | @note the range might get expanded and the actual stop_id used for the | ||
| 4827 | querying will be updated. | ||
| 4828 | @param[out] num_pages number of pages tracked | ||
| 4829 | @return Operation status. | ||
| 4830 | @retval 0 Success | ||
| 4831 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4832 | ✗ | static int innobase_page_track_get_num_page_ids(uint64_t *start_id, | |
| 4833 | uint64_t *stop_id, | ||
| 4834 | uint64_t *num_pages) { | ||
| 4835 | ✗ | if (srv_read_only_mode) { | |
| 4836 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4837 | ✗ | return ER_READ_ONLY_MODE; | |
| 4838 | } | ||
| 4839 | |||
| 4840 | ✗ | auto err = arch_page_sys->get_num_pages(*start_id, *stop_id, num_pages); | |
| 4841 | |||
| 4842 | ✗ | if (err != 0) { | |
| 4843 | ✗ | DBUG_PRINT("page_archiver", ("Fetch Pages")); | |
| 4844 | ✗ | DBUG_PRINT("page_archiver", ("Can't fetch pages")); | |
| 4845 | } | ||
| 4846 | |||
| 4847 | ✗ | return (err); | |
| 4848 | } | ||
| 4849 | |||
| 4850 | /** Fetch the page tracking status. | ||
| 4851 | @param[out] status vector of a pair of (ID, bool) where ID is the | ||
| 4852 | start/stop point and bool is true if the ID is a start point else false */ | ||
| 4853 | ✗ | static void innobase_page_track_get_status( | |
| 4854 | std::vector<std::pair<lsn_t, bool>> &status) { | ||
| 4855 | ✗ | if (srv_read_only_mode) { | |
| 4856 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4857 | ✗ | return; | |
| 4858 | } | ||
| 4859 | |||
| 4860 | ✗ | arch_page_sys->get_status(status); | |
| 4861 | } | ||
| 4862 | |||
| 4863 | /** Gives the file extension of an InnoDB single-table tablespace. */ | ||
| 4864 | static const char *ha_innobase_exts[] = {dot_ext[IBD], NullS}; | ||
| 4865 | |||
| 4866 | /** This function checks if the given db.tablename is a system table | ||
| 4867 | supported by Innodb and is used as an initializer for the data member | ||
| 4868 | is_supported_system_table of InnoDB storage engine handlerton. | ||
| 4869 | Except general_log and slow_log, currently all system tables are supported | ||
| 4870 | by InnoDB. Please don't add any SE-specific system tables here. | ||
| 4871 | |||
| 4872 | @param is_sql_layer_system_table if the supplied db.table_name is a SQL | ||
| 4873 | layer system table. | ||
| 4874 | |||
| 4875 | @return whether the table name is supported */ | ||
| 4876 | |||
| 4877 | 1031468 | static bool innobase_is_supported_system_table(const char *, const char *, | |
| 4878 | bool is_sql_layer_system_table) { | ||
| 4879 | // Currently InnoDB does not support any other SE specific system tables. | ||
| 4880 | 1031468 | return is_sql_layer_system_table; | |
| 4881 | } | ||
| 4882 | |||
| 4883 | /** Rotate the encrypted tablespace keys according to master key | ||
| 4884 | rotation. | ||
| 4885 | @return false on success, true on failure */ | ||
| 4886 | 1182 | bool innobase_encryption_key_rotation() { | |
| 4887 | 1182 | byte *master_key = nullptr; | |
| 4888 | 1182 | bool ret = false; | |
| 4889 | dberr_t err; | ||
| 4890 | |||
| 4891 | /* Pause here to try other locks while this thread holds the backup locks. */ | ||
| 4892 |
2/4✓ Branch 0 taken 1182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1182 times.
✗ Branch 3 not taken.
|
1182 | DEBUG_SYNC_C("ib_pause_encryption_rotate"); |
| 4893 | |||
| 4894 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1182 times.
|
1182 | if (srv_read_only_mode) { |
| 4895 | ✗ | my_error(ER_INNODB_READ_ONLY, MYF(0)); | |
| 4896 | ✗ | return (true); | |
| 4897 | } | ||
| 4898 | |||
| 4899 | /* Take mutex as master_key_id is going to be changed. */ | ||
| 4900 |
1/2✓ Branch 0 taken 1182 times.
✗ Branch 1 not taken.
|
1182 | mutex_enter(&master_key_id_mutex); |
| 4901 | |||
| 4902 | /* Check if keyring loaded and the currently master key | ||
| 4903 | can be fetched. */ | ||
| 4904 |
3/4✓ Branch 0 taken 1182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1163 times.
✓ Branch 3 taken 19 times.
|
1182 | if (Encryption::get_master_key_id() != Encryption::DEFAULT_MASTER_KEY_ID) { |
| 4905 | uint32_t master_key_id; | ||
| 4906 | |||
| 4907 | 1163 | Encryption::get_master_key(&master_key_id, &master_key); | |
| 4908 | |||
| 4909 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1148 times.
|
1163 | if (master_key == nullptr) { |
| 4910 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 4911 | 15 | ret = true; | |
| 4912 | 15 | goto error_exit; | |
| 4913 | } | ||
| 4914 |
1/2✓ Branch 0 taken 1148 times.
✗ Branch 1 not taken.
|
1148 | my_free(master_key); |
| 4915 | } | ||
| 4916 | |||
| 4917 | 1167 | master_key = nullptr; | |
| 4918 | |||
| 4919 | /* Generate the new master key. */ | ||
| 4920 | 1167 | Encryption::create_master_key(&master_key); | |
| 4921 | |||
| 4922 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1154 times.
|
1165 | if (master_key == nullptr) { |
| 4923 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 4924 | 11 | ret = true; | |
| 4925 | 11 | goto error_exit; | |
| 4926 | } | ||
| 4927 | |||
| 4928 | /* Rotate all IBD and IBU tablespace that need it. */ | ||
| 4929 |
2/4✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1150 times.
|
1154 | if (fil_encryption_rotate() > 0) { |
| 4930 | ✗ | my_free(master_key); | |
| 4931 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 4932 | ✗ | goto error_exit; | |
| 4933 | } | ||
| 4934 | |||
| 4935 |
1/2✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
|
1150 | err = log_encryption_on_master_key_changed(*log_sys); |
| 4936 | 1150 | ret = (err != DB_SUCCESS); | |
| 4937 | |||
| 4938 | /* If rotation failure, return error */ | ||
| 4939 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1150 times.
|
1150 | if (ret) { |
| 4940 | ✗ | my_free(master_key); | |
| 4941 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 4942 | ✗ | goto error_exit; | |
| 4943 | } | ||
| 4944 | |||
| 4945 | /* Rotate encrypted session temporary tablespaces */ | ||
| 4946 |
1/2✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
|
1150 | ibt::tbsp_pool->rotate_encryption_keys(); |
| 4947 | |||
| 4948 |
1/2✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
|
1150 | my_free(master_key); |
| 4949 | |||
| 4950 | 1176 | error_exit: | |
| 4951 | /* Release the mutex. */ | ||
| 4952 |
1/2✓ Branch 0 taken 1176 times.
✗ Branch 1 not taken.
|
1176 | mutex_exit(&master_key_id_mutex); |
| 4953 | |||
| 4954 | 1176 | return (ret); | |
| 4955 | } | ||
| 4956 | |||
| 4957 | 9498 | bool innobase_fix_default_table_encryption(ulong encryption_option, | |
| 4958 | bool is_server_starting) { | ||
| 4959 |
2/2✓ Branch 0 taken 9460 times.
✓ Branch 1 taken 38 times.
|
9498 | if (!srv_read_only_mode) { |
| 4960 | 9460 | return fil_crypt_set_encrypt_tables( | |
| 4961 | static_cast<enum_default_table_encryption>(encryption_option), | ||
| 4962 | 9460 | is_server_starting); | |
| 4963 | } | ||
| 4964 | 38 | return false; | |
| 4965 | } | ||
| 4966 | |||
| 4967 | /** Fix the empty UUID of tablespaces like system, temp etc by generating | ||
| 4968 | a new master key and do key rotation. These tablespaces if encrypted | ||
| 4969 | during startup, will be encrypted with tablespace key which has empty UUID | ||
| 4970 | @return false on success, true on failure */ | ||
| 4971 | 9450 | bool innobase_fix_tablespaces_empty_uuid() { | |
| 4972 | #ifdef UNIV_DEBUG | ||
| 4973 | /* This API is called only after uuid is ready */ | ||
| 4974 | 9450 | srv_is_uuid_ready = true; | |
| 4975 | #endif /* UNIV_DEBUG */ | ||
| 4976 | |||
| 4977 | /* If we are in read only mode, we cannot do rotation but it | ||
| 4978 | is OK */ | ||
| 4979 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 9412 times.
|
9450 | if (srv_read_only_mode) { |
| 4980 | 38 | return (false); | |
| 4981 | } | ||
| 4982 | |||
| 4983 | /* We only need to handle the case when an encrypted tablespace | ||
| 4984 | is created at startup. If it is > 1, it means we already have fixed | ||
| 4985 | the UUID */ | ||
| 4986 |
3/4✓ Branch 0 taken 9412 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 9359 times.
|
9412 | if (Encryption::get_master_key_id() > 1) { |
| 4987 | 53 | return (false); | |
| 4988 | } | ||
| 4989 | |||
| 4990 |
1/2✓ Branch 0 taken 9359 times.
✗ Branch 1 not taken.
|
9359 | if (!default_master_key_used) { |
| 4991 | 9359 | return (false); | |
| 4992 | } | ||
| 4993 | |||
| 4994 | ✗ | byte *master_key = nullptr; | |
| 4995 | uint32_t master_key_id; | ||
| 4996 | ✗ | Encryption::get_master_key(&master_key_id, &master_key); | |
| 4997 | |||
| 4998 | ✗ | if (master_key == nullptr) { | |
| 4999 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 5000 | ✗ | return (true); | |
| 5001 | } | ||
| 5002 | ✗ | my_free(master_key); | |
| 5003 | |||
| 5004 | ✗ | master_key = nullptr; | |
| 5005 | |||
| 5006 | /* Generate the new master key. */ | ||
| 5007 | ✗ | Encryption::create_master_key(&master_key); | |
| 5008 | |||
| 5009 | ✗ | if (master_key == nullptr) { | |
| 5010 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 5011 | ✗ | return (true); | |
| 5012 | } | ||
| 5013 | |||
| 5014 | /** Check if sys, temp need rotation to fix the empty uuid */ | ||
| 5015 | ✗ | space_id_vec space_ids; | |
| 5016 | |||
| 5017 | ✗ | space_ids.push_back(srv_sys_space.space_id()); | |
| 5018 | ✗ | space_ids.push_back(srv_tmp_space.space_id()); | |
| 5019 | ✗ | space_ids.push_back(dict_sys_t::s_dict_space_id); | |
| 5020 | |||
| 5021 | #ifdef UNIV_DEBUG | ||
| 5022 | /* Currently all session temp tablespaces that use empty uuid | ||
| 5023 | are destroyed. So if there is encrypted sesion temp tablespace | ||
| 5024 | we assert here */ | ||
| 5025 | ✗ | const auto find_encrypted = [&](const ibt::Tablespace *ts) { | |
| 5026 | ✗ | if (ts->is_encrypted()) { | |
| 5027 | ✗ | ut_ad(0); | |
| 5028 | } | ||
| 5029 | ✗ | }; | |
| 5030 | |||
| 5031 | ✗ | ibt::tbsp_pool->iterate_active_tbsp(find_encrypted); | |
| 5032 | #endif /* UNIV_DEBUG */ | ||
| 5033 | |||
| 5034 | ✗ | undo::spaces->s_lock(); | |
| 5035 | ✗ | for (auto undo_space : undo::spaces->m_spaces) { | |
| 5036 | /* We already added system tablespace */ | ||
| 5037 | ✗ | if (undo_space->id() == TRX_SYS_SPACE) { | |
| 5038 | ✗ | continue; | |
| 5039 | } | ||
| 5040 | ✗ | space_ids.push_back(undo_space->id()); | |
| 5041 | } | ||
| 5042 | ✗ | undo::spaces->s_unlock(); | |
| 5043 | |||
| 5044 | /* Rotate log tablespace */ | ||
| 5045 | |||
| 5046 | ✗ | my_free(master_key); | |
| 5047 | |||
| 5048 | ✗ | return (false); | |
| 5049 | } | ||
| 5050 | |||
| 5051 | /** Enable or Disable SE write ahead logging. | ||
| 5052 | @param[in] thd connection THD | ||
| 5053 | @param[in] enable enable/disable redo logging | ||
| 5054 | @return true iff failed. */ | ||
| 5055 | 38 | static bool innobase_redo_set_state(THD *thd, bool enable) { | |
| 5056 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (srv_read_only_mode) { |
| 5057 | ✗ | my_error(ER_INNODB_READ_ONLY, MYF(0)); | |
| 5058 | ✗ | return (true); | |
| 5059 | } | ||
| 5060 | |||
| 5061 | 38 | int err = 0; | |
| 5062 | |||
| 5063 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20 times.
|
38 | if (enable) { |
| 5064 | 18 | err = mtr_t::s_logging.enable(thd); | |
| 5065 | } else { | ||
| 5066 | 20 | err = mtr_t::s_logging.disable(thd); | |
| 5067 | } | ||
| 5068 | |||
| 5069 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 36 times.
|
38 | if (err != 0) { |
| 5070 | 2 | return (true); | |
| 5071 | } | ||
| 5072 | |||
| 5073 | 36 | set_srv_redo_log(enable); | |
| 5074 | 36 | return (false); | |
| 5075 | } | ||
| 5076 | |||
| 5077 | /** Return partitioning flags. */ | ||
| 5078 | 2318064 | static uint innobase_partition_flags() { | |
| 5079 | return (HA_CAN_EXCHANGE_PARTITION | HA_CANNOT_PARTITION_FK | | ||
| 5080 | 2318064 | HA_TRUNCATE_PARTITION_PRECLOSE); | |
| 5081 | } | ||
| 5082 | #endif /* !UNIV_HOTBACKUP */ | ||
| 5083 | |||
| 5084 | /** Update log_checksum_algorithm_ptr with a pointer to the function | ||
| 5085 | corresponding to whether checksums are enabled. | ||
| 5086 | @param[in] check whether redo log block checksums are enabled */ | ||
| 5087 | #ifndef UNIV_HOTBACKUP | ||
| 5088 | static | ||
| 5089 | #endif /* !UNIV_HOTBACKUP */ | ||
| 5090 | void | ||
| 5091 | 9733 | innodb_log_checksums_func_update(bool check) { | |
| 5092 |
2/2✓ Branch 0 taken 9729 times.
✓ Branch 1 taken 4 times.
|
9733 | log_checksum_algorithm_ptr.store(check ? log_block_calc_checksum_crc32 |
| 5093 | : log_block_calc_checksum_none); | ||
| 5094 | 9733 | } | |
| 5095 | |||
| 5096 | #ifndef UNIV_HOTBACKUP | ||
| 5097 | |||
| 5098 | /** Minimum expected tablespace size. (5M) */ | ||
| 5099 | static const ulint MIN_EXPECTED_TABLESPACE_SIZE = 5 * 1024 * 1024; | ||
| 5100 | |||
| 5101 | /** Validate innodb_undo_tablespaces. Log a warning if it was set | ||
| 5102 | explicitly. */ | ||
| 5103 | 9732 | static void innodb_undo_tablespaces_deprecate() { | |
| 5104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9732 times.
|
9732 | if (sysvar_source_svc == nullptr) { |
| 5105 | ✗ | return; | |
| 5106 | } | ||
| 5107 | |||
| 5108 | static const char *variable_name = "innodb_undo_tablespaces"; | ||
| 5109 | enum enum_variable_source source; | ||
| 5110 | |||
| 5111 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9732 times.
|
9732 | if (sysvar_source_svc->get(variable_name, |
| 5112 |
1/2✓ Branch 0 taken 9732 times.
✗ Branch 1 not taken.
|
9732 | static_cast<unsigned int>(strlen(variable_name)), |
| 5113 | &source)) { | ||
| 5114 | ✗ | return; | |
| 5115 | } | ||
| 5116 | |||
| 5117 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9724 times.
|
9732 | if (source != COMPILED) { |
| 5118 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | ib::warn(ER_IB_MSG_DEPRECATED_INNODB_UNDO_TABLESPACES); |
| 5119 | 8 | srv_undo_tablespaces = FSP_IMPLICIT_UNDO_TABLESPACES; | |
| 5120 | } | ||
| 5121 | } | ||
| 5122 | |||
| 5123 | /** Validate innodb_parallel_doublewrite_path. Log a warning if it was set | ||
| 5124 | explicitly. */ | ||
| 5125 | 9726 | static void innodb_parallel_doublewrite_path_deprecate() { | |
| 5126 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | if (sysvar_source_svc != nullptr) { |
| 5127 | static const char *variable_name = "innodb_parallel_doublewrite_path"; | ||
| 5128 | enum enum_variable_source source; | ||
| 5129 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | if (!sysvar_source_svc->get( |
| 5130 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | variable_name, static_cast<unsigned int>(strlen(variable_name)), |
| 5131 | &source)) { | ||
| 5132 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9725 times.
|
9726 | if (source != COMPILED) { |
| 5133 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | ib::warn(ER_IB_MSG_DEPRECATED_INNODB_PARALLEL_DOUBLEWRITE_PATH); |
| 5134 | } | ||
| 5135 | } | ||
| 5136 | } | ||
| 5137 | 9726 | } | |
| 5138 | |||
| 5139 | /** Validate innodb_parallel_dblwr_encrypt. Log a warning if it was set | ||
| 5140 | explicitly. */ | ||
| 5141 | 9729 | static void innodb_parallel_dblwr_encrypt_deprecate() { | |
| 5142 |
1/2✓ Branch 0 taken 9729 times.
✗ Branch 1 not taken.
|
9729 | if (sysvar_source_svc != nullptr) { |
| 5143 | static const char *variable_name = "innodb_parallel_dblwr_encrypt"; | ||
| 5144 | enum enum_variable_source source; | ||
| 5145 |
1/2✓ Branch 0 taken 9729 times.
✗ Branch 1 not taken.
|
9729 | if (!sysvar_source_svc->get( |
| 5146 |
1/2✓ Branch 0 taken 9729 times.
✗ Branch 1 not taken.
|
9729 | variable_name, static_cast<unsigned int>(strlen(variable_name)), |
| 5147 | &source)) { | ||
| 5148 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 9713 times.
|
9729 | if (source != COMPILED) { |
| 5149 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | ib::warn(ER_IB_MSG_DEPRECATED_INNODB_PARALLEL_DBLWR_ENCRYPT); |
| 5150 | } | ||
| 5151 | } | ||
| 5152 | } | ||
| 5153 | 9729 | } | |
| 5154 | |||
| 5155 | /** Initialize and normalize innodb_buffer_pool_size. */ | ||
| 5156 | 9726 | static void innodb_buffer_pool_size_init() { | |
| 5157 | #ifdef UNIV_DEBUG | ||
| 5158 | 9726 | ulong srv_buf_pool_instances_org = srv_buf_pool_instances; | |
| 5159 | #endif /* UNIV_DEBUG */ | ||
| 5160 | |||
| 5161 | /* If innodb_dedicated_server == ON */ | ||
| 5162 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
9726 | if (srv_dedicated_server && sysvar_source_svc != nullptr) { |
| 5163 | static const char *variable_name = "innodb_buffer_pool_size"; | ||
| 5164 | enum enum_variable_source source; | ||
| 5165 | ✗ | if (!sysvar_source_svc->get( | |
| 5166 | ✗ | variable_name, static_cast<unsigned int>(strlen(variable_name)), | |
| 5167 | &source)) { | ||
| 5168 | ✗ | if (source == COMPILED) { | |
| 5169 | ✗ | double server_mem = get_sys_mem(); | |
| 5170 | |||
| 5171 | ✗ | if (server_mem < 1.0) { | |
| 5172 | ; | ||
| 5173 | ✗ | } else if (server_mem <= 4.0) { | |
| 5174 | ✗ | srv_buf_pool_size = static_cast<ulint>(server_mem * 0.5 * GB); | |
| 5175 | } else | ||
| 5176 | ✗ | srv_buf_pool_size = static_cast<ulint>(server_mem * 0.75 * GB); | |
| 5177 | } else { | ||
| 5178 | ✗ | ib::warn(ER_IB_MSG_533) | |
| 5179 | << "Option innodb_dedicated_server" | ||
| 5180 | " is ignored for" | ||
| 5181 | " innodb_buffer_pool_size because" | ||
| 5182 | ✗ | " innodb_buffer_pool_size=" | |
| 5183 | ✗ | << srv_buf_pool_curr_size << " is specified explicitly."; | |
| 5184 | } | ||
| 5185 | } | ||
| 5186 | } | ||
| 5187 | |||
| 5188 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 9703 times.
|
9726 | if (srv_buf_pool_size >= BUF_POOL_SIZE_THRESHOLD) { |
| 5189 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 15 times.
|
23 | if (srv_buf_pool_instances == srv_buf_pool_instances_default) { |
| 5190 | #if defined(_WIN32) && !defined(_WIN64) | ||
| 5191 | /* Do not allocate too large of a buffer pool on | ||
| 5192 | Windows 32-bit systems, which can have trouble | ||
| 5193 | allocating larger single contiguous memory blocks. */ | ||
| 5194 | srv_buf_pool_instances = | ||
| 5195 | std::min(static_cast<ulong>(MAX_BUFFER_POOLS), | ||
| 5196 | static_cast<ulong>(srv_buf_pool_size / (128 * 1024 * 1024))); | ||
| 5197 | #else /* defined(_WIN32) && !defined(_WIN64) */ | ||
| 5198 | /* Default to 8 instances when size > 1GB. */ | ||
| 5199 | 8 | srv_buf_pool_instances = 8; | |
| 5200 | #endif /* defined(_WIN32) && !defined(_WIN64) */ | ||
| 5201 | } | ||
| 5202 | } else { | ||
| 5203 | /* If buffer pool is less than 1 GiB, assume fewer | ||
| 5204 | threads. Also use only one buffer pool instance. */ | ||
| 5205 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9699 times.
|
9703 | if (srv_buf_pool_instances != srv_buf_pool_instances_default && |
| 5206 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | srv_buf_pool_instances != 1) { |
| 5207 | /* We can't distinguish whether the user has explicitly | ||
| 5208 | started mysqld with --innodb-buffer-pool-instances=0, | ||
| 5209 | (srv_buf_pool_instances_default is 0) or has not | ||
| 5210 | specified that option at all. Thus we have the | ||
| 5211 | limitation that if the user started with =0, we | ||
| 5212 | will not emit a warning here, but we should actually | ||
| 5213 | do so. */ | ||
| 5214 | 2 | ib::info(ER_IB_MSG_534) | |
| 5215 | << "Adjusting innodb_buffer_pool_instances" | ||
| 5216 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | " from " |
| 5217 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | << srv_buf_pool_instances |
| 5218 | << " to 1" | ||
| 5219 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | " since innodb_buffer_pool_size is less than " |
| 5220 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | << BUF_POOL_SIZE_THRESHOLD / (1024 * 1024) << " MiB"; |
| 5221 | } | ||
| 5222 | |||
| 5223 | 9703 | srv_buf_pool_instances = 1; | |
| 5224 | } | ||
| 5225 | |||
| 5226 | #ifdef UNIV_DEBUG | ||
| 5227 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9725 times.
|
9726 | if (srv_buf_pool_debug && |
| 5228 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | srv_buf_pool_instances_org != srv_buf_pool_instances_default) { |
| 5229 | 1 | srv_buf_pool_instances = srv_buf_pool_instances_org; | |
| 5230 | }; | ||
| 5231 | #endif /* UNIV_DEBUG */ | ||
| 5232 | |||
| 5233 | 9726 | srv_buf_pool_chunk_unit = buf_pool_adjust_chunk_unit(srv_buf_pool_chunk_unit); | |
| 5234 | 9726 | srv_buf_pool_size = buf_pool_size_align(srv_buf_pool_size); | |
| 5235 | |||
| 5236 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_ad(srv_buf_pool_chunk_unit >= srv_buf_pool_chunk_unit_min); |
| 5237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_ad(srv_buf_pool_chunk_unit <= srv_buf_pool_chunk_unit_max); |
| 5238 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_ad(srv_buf_pool_chunk_unit % srv_buf_pool_chunk_unit_blk_sz == 0); |
| 5239 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_ad(srv_buf_pool_chunk_unit % UNIV_PAGE_SIZE == 0); |
| 5240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_ad(0 == |
| 5241 | srv_buf_pool_size % (srv_buf_pool_chunk_unit * srv_buf_pool_instances)); | ||
| 5242 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_ad(srv_buf_pool_chunk_unit * srv_buf_pool_instances <= srv_buf_pool_size); |
| 5243 | |||
| 5244 | 9726 | srv_buf_pool_curr_size = srv_buf_pool_size; | |
| 5245 | |||
| 5246 | /* Do not enable backoff algorithm for small buffer pool. */ | ||
| 5247 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9724 times.
|
9726 | if (!innodb_empty_free_list_algorithm_allowed( |
| 5248 | static_cast<srv_empty_free_list_t>(srv_empty_free_list_algorithm))) { | ||
| 5249 | 2 | sql_print_information( | |
| 5250 | "InnoDB: innodb_empty_free_list_algorithm has been changed to legacy " | ||
| 5251 | "because of small buffer pool size. In order to use backoff, " | ||
| 5252 | "increase buffer pool at least up to 20MB.\n"); | ||
| 5253 | 2 | srv_empty_free_list_algorithm = SRV_EMPTY_FREE_LIST_LEGACY; | |
| 5254 | } | ||
| 5255 | 9726 | } | |
| 5256 | |||
| 5257 | template <size_t N> | ||
| 5258 | 58356 | static bool innodb_variable_is_set(const char (&var_name)[N]) { | |
| 5259 | enum enum_variable_source source; | ||
| 5260 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29178 times.
|
58356 | ut_a(sysvar_source_svc != nullptr); |
| 5261 |
1/2✓ Branch 0 taken 29178 times.
✗ Branch 1 not taken.
|
58356 | const auto svc_result = sysvar_source_svc->get(var_name, N - 1, &source); |
| 5262 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29178 times.
|
58356 | ut_a(!svc_result); |
| 5263 | 58356 | return source != COMPILED; | |
| 5264 | } | ||
| 5265 | |||
| 5266 | 9726 | static bool innodb_redo_log_capacity_is_set() { | |
| 5267 | 9726 | return innodb_variable_is_set("innodb_redo_log_capacity"); | |
| 5268 | } | ||
| 5269 | |||
| 5270 | 9726 | bool innodb_log_file_size_is_set() { | |
| 5271 | 9726 | return innodb_variable_is_set("innodb_log_file_size"); | |
| 5272 | } | ||
| 5273 | |||
| 5274 | 9726 | bool innodb_log_n_files_is_set() { | |
| 5275 | 9726 | return innodb_variable_is_set("innodb_log_files_in_group"); | |
| 5276 | } | ||
| 5277 | |||
| 5278 | /** Initialize srv_redo_log_capacity / srv_redo_log_capacity_used. */ | ||
| 5279 | 9726 | static void innodb_redo_log_capacity_init() { | |
| 5280 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | DBUG_TRACE; |
| 5281 | |||
| 5282 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(MB % UNIV_PAGE_SIZE == 0); |
| 5283 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(srv_redo_log_capacity % MB == 0); |
| 5284 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(srv_redo_log_capacity > 0); |
| 5285 | |||
| 5286 | 9726 | srv_redo_log_capacity_used = srv_redo_log_capacity; | |
| 5287 | |||
| 5288 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (sysvar_source_svc == nullptr) { |
| 5289 | ✗ | return; | |
| 5290 | } | ||
| 5291 | |||
| 5292 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | const bool file_size_set = innodb_log_file_size_is_set(); |
| 5293 | |||
| 5294 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | const bool n_files_set = innodb_log_n_files_is_set(); |
| 5295 | |||
| 5296 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | bool capacity_set = innodb_redo_log_capacity_is_set(); |
| 5297 | |||
| 5298 |
2/2✓ Branch 0 taken 9513 times.
✓ Branch 1 taken 213 times.
|
9726 | if (capacity_set) { |
| 5299 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 9486 times.
|
9513 | if (file_size_set) { |
| 5300 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | ib::warn(ER_IB_MSG_LOG_PARAMS_FILE_SIZE_UNUSED); |
| 5301 | } | ||
| 5302 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9511 times.
|
9513 | if (n_files_set) { |
| 5303 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ib::warn(ER_IB_MSG_LOG_PARAMS_N_FILES_UNUSED); |
| 5304 | } | ||
| 5305 | } else { | ||
| 5306 |
4/4✓ Branch 0 taken 210 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 208 times.
|
213 | if (file_size_set || n_files_set) { |
| 5307 | 5 | srv_redo_log_capacity_used = srv_log_file_size * srv_log_n_files; | |
| 5308 | 5 | capacity_set = true; // do not change it in dedicated_server mode | |
| 5309 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | ib::warn(ER_IB_MSG_LOG_PARAMS_LEGACY_USAGE, srv_redo_log_capacity_used); |
| 5310 | } | ||
| 5311 | } | ||
| 5312 | |||
| 5313 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (srv_dedicated_server) { |
| 5314 | double auto_buf_pool_size_in_gb; | ||
| 5315 | static const char *var_name_buf_pool_size = "innodb_buffer_pool_size"; | ||
| 5316 | enum enum_variable_source source; | ||
| 5317 | |||
| 5318 | ✗ | auto_buf_pool_size_in_gb = static_cast<double>(srv_buf_pool_size / GB); | |
| 5319 | |||
| 5320 | /* If user has set buffer pool size in .cnf, we will not use it as base | ||
| 5321 | line for log_file_size auto tuning, instead, we will get the value of | ||
| 5322 | possible tuned buffer pool size. */ | ||
| 5323 | ✗ | if (!sysvar_source_svc->get( | |
| 5324 | var_name_buf_pool_size, | ||
| 5325 | ✗ | static_cast<unsigned int>(strlen(var_name_buf_pool_size)), | |
| 5326 | &source)) { | ||
| 5327 | ✗ | if (source != COMPILED) { | |
| 5328 | ✗ | double server_mem = get_sys_mem(); | |
| 5329 | |||
| 5330 | #ifdef UNIV_DEBUG_DEDICATED | ||
| 5331 | server_mem = srv_debug_system_mem_size / GB; | ||
| 5332 | #endif /* UNIV_DEBUG_DEDICATED */ | ||
| 5333 | |||
| 5334 | ✗ | if (server_mem < 1.0) { | |
| 5335 | ; | ||
| 5336 | ✗ | } else if (server_mem <= 4.0) { | |
| 5337 | ✗ | auto_buf_pool_size_in_gb = static_cast<double>(server_mem * 0.5); | |
| 5338 | } else | ||
| 5339 | ✗ | auto_buf_pool_size_in_gb = static_cast<double>(server_mem * 0.75); | |
| 5340 | } | ||
| 5341 | } | ||
| 5342 | |||
| 5343 | ✗ | if (!capacity_set) { | |
| 5344 | /* We update srv_redo_log_capacity (underlying sysvar variable), | ||
| 5345 | because that is what innodb_dedicated_server is expected to do. */ | ||
| 5346 | ✗ | if (auto_buf_pool_size_in_gb < 1.0) { | |
| 5347 | ✗ | ut_ad(srv_redo_log_capacity == 100 * 1024 * 1024); | |
| 5348 | ✗ | } else if (auto_buf_pool_size_in_gb < 8.0) { | |
| 5349 | ✗ | srv_redo_log_capacity = | |
| 5350 | ✗ | static_cast<ulong>(round(auto_buf_pool_size_in_gb)) * 512ULL * MB; | |
| 5351 | ✗ | } else if (auto_buf_pool_size_in_gb <= 128.0) { | |
| 5352 | ✗ | srv_redo_log_capacity = | |
| 5353 | ✗ | static_cast<ulong>(round(auto_buf_pool_size_in_gb * 0.75)) * GB; | |
| 5354 | } else { | ||
| 5355 | ✗ | constexpr os_offset_t LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER = 128 * GB; | |
| 5356 | |||
| 5357 | static_assert( | ||
| 5358 | LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER <= LOG_CAPACITY_MAX, | ||
| 5359 | "Redo log capacity, for the dedicated server, is too big."); | ||
| 5360 | |||
| 5361 | ✗ | srv_redo_log_capacity = LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER; | |
| 5362 | } | ||
| 5363 | ✗ | srv_redo_log_capacity_used = srv_redo_log_capacity; | |
| 5364 | |||
| 5365 | } else { | ||
| 5366 | ✗ | ut_a(srv_redo_log_capacity_used % MB == 0); | |
| 5367 | ✗ | ib::warn(ER_IB_MSG_LOG_PARAMS_DEDICATED_SERVER_IGNORED, | |
| 5368 | ✗ | ulonglong{srv_redo_log_capacity_used / MB}); | |
| 5369 | } | ||
| 5370 | } | ||
| 5371 | |||
| 5372 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(LOG_CAPACITY_MIN <= srv_redo_log_capacity_used); |
| 5373 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(srv_redo_log_capacity_used <= LOG_CAPACITY_MAX); |
| 5374 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(srv_redo_log_capacity_used % MB == 0); |
| 5375 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | } |
| 5376 | |||
| 5377 | /** Initialize, validate and normalize the InnoDB startup parameters. | ||
| 5378 | @return failure code | ||
| 5379 | @retval 0 on success | ||
| 5380 | @retval HA_ERR_OUT_OF_MEM when out of memory | ||
| 5381 | @retval HA_ERR_INITIALIZATION when some parameters are out of range */ | ||
| 5382 | 9733 | static int innodb_init_params() { | |
| 5383 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | DBUG_TRACE; |
| 5384 | |||
| 5385 | static char current_dir[3]; | ||
| 5386 | char *default_path; | ||
| 5387 | |||
| 5388 | /* First calculate the default path for innodb_data_home_dir etc., | ||
| 5389 | in case the user has not given any value. */ | ||
| 5390 | |||
| 5391 | /* It's better to use current lib, to keep paths short */ | ||
| 5392 | 9733 | current_dir[0] = FN_CURLIB; | |
| 5393 | 9733 | current_dir[1] = FN_LIBCHAR; | |
| 5394 | 9733 | current_dir[2] = 0; | |
| 5395 | 9733 | default_path = current_dir; | |
| 5396 | |||
| 5397 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | std::string mysqld_datadir{default_path}; |
| 5398 | |||
| 5399 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | MySQL_datadir_path = Fil_path{mysqld_datadir}; |
| 5400 | |||
| 5401 | /* Validate, normalize and interpret the InnoDB start-up parameters. */ | ||
| 5402 | |||
| 5403 | /* The default dir for data files is the datadir of MySQL */ | ||
| 5404 | |||
| 5405 | 9733 | srv_data_home = | |
| 5406 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
|
52 | (innobase_data_home_dir == nullptr || *innobase_data_home_dir == '\0') |
| 5407 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 9681 times.
|
9785 | ? default_path |
| 5408 | : innobase_data_home_dir; | ||
| 5409 | 9733 | Fil_path::normalize(srv_data_home); | |
| 5410 | |||
| 5411 | /* Validate the undo directory. */ | ||
| 5412 |
3/4✓ Branch 0 taken 55 times.
✓ Branch 1 taken 9678 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 55 times.
|
9733 | if (srv_undo_dir == nullptr || srv_undo_dir[0] == 0) { |
| 5413 | 9678 | srv_undo_dir = default_path; | |
| 5414 | } else { | ||
| 5415 | 55 | Fil_path::normalize(srv_undo_dir); | |
| 5416 | } | ||
| 5417 | |||
| 5418 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | MySQL_undo_path = Fil_path{srv_undo_dir}; |
| 5419 | |||
| 5420 |
4/6✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9733 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 9732 times.
|
9733 | if (MySQL_undo_path.is_ancestor(default_path)) { |
| 5421 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY_LOCATION); |
| 5422 | 1 | return HA_ERR_INITIALIZATION; | |
| 5423 | } | ||
| 5424 | |||
| 5425 | /* Validate the temp directory */ | ||
| 5426 |
2/2✓ Branch 0 taken 9725 times.
✓ Branch 1 taken 7 times.
|
9732 | if (ibt::srv_temp_dir == nullptr) { |
| 5427 | 9725 | ibt::srv_temp_dir = default_path; | |
| 5428 | } else { | ||
| 5429 | os_file_type_t type; | ||
| 5430 | bool exists; | ||
| 5431 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | os_file_status(ibt::srv_temp_dir, &exists, &type); |
| 5432 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
7 | if (!exists || type != OS_FILE_TYPE_DIR) { |
| 5433 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
6 | ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_DOESNT_EXIST) |
| 5434 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | << "Invalid innodb_temp_tablespaces_dir: " << ibt::srv_temp_dir |
| 5435 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | << ". Directory doesn't exist or not valid"; |
| 5436 | 5 | return HA_ERR_INITIALIZATION; | |
| 5437 | } | ||
| 5438 | |||
| 5439 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | Fil_path temp_dir(ibt::srv_temp_dir); |
| 5440 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (temp_dir.path().empty()) { |
| 5441 | ✗ | ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_EMPTY) | |
| 5442 | ✗ | << "Invalid innodb_temp_tablespaces dir: " << ibt::srv_temp_dir | |
| 5443 | ✗ | << ". Path cannot be empty"; | |
| 5444 | ✗ | return HA_ERR_INITIALIZATION; | |
| 5445 | } | ||
| 5446 | |||
| 5447 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (strchr(ibt::srv_temp_dir, ';')) { |
| 5448 | ✗ | ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_CONTAINS_SEMICOLON) | |
| 5449 | ✗ | << "Invalid innodb_temp_tablespaces dir: " << ibt::srv_temp_dir | |
| 5450 | ✗ | << ". Path cannot contain ;"; | |
| 5451 | ✗ | return HA_ERR_INITIALIZATION; | |
| 5452 | } | ||
| 5453 | |||
| 5454 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (MySQL_datadir_path.is_ancestor( |
| 5455 |
3/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
8 | Fil_path::get_real_path(temp_dir.path()))) { |
| 5456 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_SUBDIR_OF_DATADIR) |
| 5457 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | << "Invalid innodb_temp_tablespaces_dir=" << ibt::srv_temp_dir |
| 5458 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | << ". This path should not be a subdirectory of the datadir."; |
| 5459 | 2 | return HA_ERR_INITIALIZATION; | |
| 5460 | } | ||
| 5461 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | } |
| 5462 | |||
| 5463 | 9727 | Fil_path::normalize(ibt::srv_temp_dir); | |
| 5464 | |||
| 5465 | /* The default dir for log files is the datadir of MySQL */ | ||
| 5466 | |||
| 5467 |
2/2✓ Branch 0 taken 9713 times.
✓ Branch 1 taken 14 times.
|
9727 | if (srv_log_group_home_dir == nullptr) { |
| 5468 | 9713 | srv_log_group_home_dir = default_path; | |
| 5469 | } | ||
| 5470 | 9727 | Fil_path::normalize(srv_log_group_home_dir); | |
| 5471 | |||
| 5472 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9726 times.
|
9727 | if (strchr(srv_log_group_home_dir, ';')) { |
| 5473 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_LOG_GROUP_HOME_DIR); |
| 5474 | 1 | return HA_ERR_INITIALIZATION; | |
| 5475 | } | ||
| 5476 | |||
| 5477 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (strchr(srv_undo_dir, ';')) { |
| 5478 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY); | |
| 5479 | ✗ | return HA_ERR_INITIALIZATION; | |
| 5480 | } | ||
| 5481 | |||
| 5482 | if (!is_filename_allowed(srv_buf_dump_filename, strlen(srv_buf_dump_filename), | ||
| 5483 | false)) { | ||
| 5484 | log_errlog(ERROR_LEVEL, ER_INNODB_ILLEGAL_COLON_IN_POOL); | ||
| 5485 | return HA_ERR_INITIALIZATION; | ||
| 5486 | } | ||
| 5487 | |||
| 5488 | /* Check that the value of system variable innodb_page_size was | ||
| 5489 | set correctly. Its value was put into srv_page_size. If valid, | ||
| 5490 | return the associated srv_page_size_shift. */ | ||
| 5491 | 9726 | srv_page_size_shift = page_size_validate(srv_page_size); | |
| 5492 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (!srv_page_size_shift) { |
| 5493 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_PAGE_SIZE, srv_page_size); | |
| 5494 | ✗ | return HA_ERR_INITIALIZATION; | |
| 5495 | } | ||
| 5496 | |||
| 5497 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(srv_log_buffer_size % OS_FILE_LOG_BLOCK_SIZE == 0); |
| 5498 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(srv_log_buffer_size > 0); |
| 5499 | |||
| 5500 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(srv_log_write_ahead_size % OS_FILE_LOG_BLOCK_SIZE == 0); |
| 5501 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_a(srv_log_write_ahead_size > 0); |
| 5502 | |||
| 5503 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | assert(innodb_change_buffering <= IBUF_USE_ALL); |
| 5504 | |||
| 5505 | /* Check that interdependent parameters have sane values. */ | ||
| 5506 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (srv_max_buf_pool_modified_pct < srv_max_dirty_pages_pct_lwm) { |
| 5507 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_DIRTY_WATER_MARK_NOT_LOW, | |
| 5508 | srv_max_buf_pool_modified_pct); | ||
| 5509 | ✗ | srv_max_dirty_pages_pct_lwm = srv_max_buf_pool_modified_pct; | |
| 5510 | } | ||
| 5511 | |||
| 5512 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | if (srv_max_io_capacity == SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT) { |
| 5513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (srv_io_capacity >= SRV_MAX_IO_CAPACITY_LIMIT / 2) { |
| 5514 | /* Avoid overflow. */ | ||
| 5515 | ✗ | srv_max_io_capacity = SRV_MAX_IO_CAPACITY_LIMIT; | |
| 5516 | } else { | ||
| 5517 | /* The user has not set the value. We should | ||
| 5518 | set it based on innodb_io_capacity. */ | ||
| 5519 | 9726 | srv_max_io_capacity = std::max(2 * srv_io_capacity, 2000UL); | |
| 5520 | } | ||
| 5521 | |||
| 5522 | ✗ | } else if (srv_max_io_capacity < srv_io_capacity) { | |
| 5523 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_IO_CAPACITY_EXCEEDS_MAX, | |
| 5524 | srv_max_io_capacity); | ||
| 5525 | ✗ | srv_io_capacity = srv_max_io_capacity; | |
| 5526 | } | ||
| 5527 | |||
| 5528 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (UNIV_PAGE_SIZE_DEF != srv_page_size) { |
| 5529 | ✗ | ib::warn(ER_IB_MSG_538) | |
| 5530 | << "innodb-page-size has been changed from the" | ||
| 5531 | ✗ | " default value " | |
| 5532 | ✗ | << UNIV_PAGE_SIZE_DEF << " to " << srv_page_size << "."; | |
| 5533 | } | ||
| 5534 | |||
| 5535 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (srv_log_write_ahead_size > srv_page_size) { |
| 5536 | ✗ | srv_log_write_ahead_size = srv_page_size; | |
| 5537 | } else { | ||
| 5538 | 9726 | ulong srv_log_write_ahead_size_tmp = OS_FILE_LOG_BLOCK_SIZE; | |
| 5539 | |||
| 5540 |
2/2✓ Branch 0 taken 38904 times.
✓ Branch 1 taken 9726 times.
|
48630 | while (srv_log_write_ahead_size_tmp < srv_log_write_ahead_size) { |
| 5541 | 38904 | srv_log_write_ahead_size_tmp = srv_log_write_ahead_size_tmp * 2; | |
| 5542 | } | ||
| 5543 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (srv_log_write_ahead_size_tmp != srv_log_write_ahead_size) { |
| 5544 | ✗ | srv_log_write_ahead_size = srv_log_write_ahead_size_tmp / 2; | |
| 5545 | } | ||
| 5546 | } | ||
| 5547 | |||
| 5548 | 9726 | srv_buf_pool_size = srv_buf_pool_curr_size; | |
| 5549 | |||
| 5550 | 9726 | innodb_log_checksums_func_update(srv_log_checksums); | |
| 5551 | |||
| 5552 | #ifdef HAVE_LINUX_LARGE_PAGES | ||
| 5553 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if ((os_use_large_pages = opt_large_pages)) { |
| 5554 | ✗ | os_large_page_size = opt_large_page_size; | |
| 5555 | } | ||
| 5556 | #endif /* HAVE_LINUX_LARGE_PAGES */ | ||
| 5557 | |||
| 5558 | 9726 | row_rollback_on_timeout = innobase_rollback_on_timeout; | |
| 5559 | |||
| 5560 |
2/2✓ Branch 0 taken 9723 times.
✓ Branch 1 taken 3 times.
|
9726 | if (innobase_open_files < 10) { |
| 5561 | 9723 | innobase_open_files = 300; | |
| 5562 |
4/4✓ Branch 0 taken 9700 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 9697 times.
✓ Branch 3 taken 3 times.
|
9723 | if (srv_file_per_table && table_cache_size > 300) { |
| 5563 | 9697 | innobase_open_files = table_cache_size; | |
| 5564 | } | ||
| 5565 | } | ||
| 5566 | |||
| 5567 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9725 times.
|
9726 | if (innobase_open_files > (long)open_files_limit) { |
| 5568 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | ib::warn(ER_IB_MSG_539) << "innodb_open_files should not be greater" |
| 5569 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | " than the open_files_limit.\n"; |
| 5570 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (innobase_open_files > (long)table_cache_size) { |
| 5571 | 1 | innobase_open_files = table_cache_size; | |
| 5572 | } | ||
| 5573 | } | ||
| 5574 | |||
| 5575 | 9726 | srv_innodb_status = innobase_create_status_file; | |
| 5576 | |||
| 5577 | /* Round up ddl:fts_parser_threads to nearest power of 2 number */ | ||
| 5578 | { | ||
| 5579 | 9726 | ulong n_parser_threads = 1; | |
| 5580 | |||
| 5581 |
2/2✓ Branch 0 taken 9726 times.
✓ Branch 1 taken 9726 times.
|
19452 | while (n_parser_threads < ddl::fts_parser_threads) { |
| 5582 | 9726 | n_parser_threads <<= 1; | |
| 5583 | } | ||
| 5584 | |||
| 5585 | 9726 | ddl::fts_parser_threads = n_parser_threads; | |
| 5586 | } | ||
| 5587 | |||
| 5588 | /* Store the default charset-collation number of this MySQL | ||
| 5589 | installation */ | ||
| 5590 | |||
| 5591 | 9726 | data_mysql_default_charset_coll = (ulint)default_charset_info->number; | |
| 5592 | |||
| 5593 | 9726 | innobase_commit_concurrency_init_default(); | |
| 5594 | |||
| 5595 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 9713 times.
|
9726 | if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { |
| 5596 | 13 | srv_read_only_mode = true; | |
| 5597 | } | ||
| 5598 | |||
| 5599 | 9726 | high_level_read_only = | |
| 5600 |
4/4✓ Branch 0 taken 9671 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 9666 times.
|
9726 | srv_read_only_mode || srv_force_recovery > SRV_FORCE_NO_TRX_UNDO; |
| 5601 | |||
| 5602 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 9671 times.
|
9726 | if (srv_read_only_mode) { |
| 5603 |
2/4✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
|
55 | ib::info(ER_IB_MSG_540) << "Started in read only mode"; |
| 5604 | |||
| 5605 | /* There is no write except to intrinsic table and so turn-off | ||
| 5606 | doublewrite mechanism completely. */ | ||
| 5607 | 55 | dblwr::g_mode = dblwr::Mode::OFF; | |
| 5608 | } | ||
| 5609 | |||
| 5610 | #ifdef LINUX_NATIVE_AIO | ||
| 5611 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | if (srv_use_native_aio) { |
| 5612 |
2/4✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9726 times.
✗ Branch 3 not taken.
|
9726 | ib::info(ER_IB_MSG_541) << "Using Linux native AIO"; |
| 5613 | } | ||
| 5614 | #elif !defined _WIN32 | ||
| 5615 | /* Currently native AIO is supported only on Windows and Linux | ||
| 5616 | and that also when the support is compiled in. In all other | ||
| 5617 | cases, we ignore the setting of innodb_use_native_aio. */ | ||
| 5618 | srv_use_native_aio = false; | ||
| 5619 | #endif | ||
| 5620 | |||
| 5621 | #ifndef _WIN32 | ||
| 5622 | /* Check if innodb_dedicated_server == ON and O_DIRECT is supported */ | ||
| 5623 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9726 times.
|
9726 | if (srv_dedicated_server && sysvar_source_svc != nullptr && |
| 5624 | ✗ | os_is_o_direct_supported()) { | |
| 5625 | static const char *variable_name = "innodb_flush_method"; | ||
| 5626 | enum enum_variable_source source; | ||
| 5627 | |||
| 5628 | ✗ | if (!sysvar_source_svc->get(variable_name, strlen(variable_name), | |
| 5629 | &source)) { | ||
| 5630 | /* If innodb_flush_method is not specified explicitly */ | ||
| 5631 | ✗ | if (source == COMPILED) { | |
| 5632 | ✗ | innodb_flush_method = static_cast<ulong>(SRV_UNIX_O_DIRECT_NO_FSYNC); | |
| 5633 | } else { | ||
| 5634 | ✗ | ib::warn(ER_IB_MSG_542) | |
| 5635 | << "Option innodb_dedicated_server" | ||
| 5636 | " is ignored for innodb_flush_method" | ||
| 5637 | ✗ | "because innodb_flush_method=" | |
| 5638 | ✗ | << innodb_flush_method_names[innodb_flush_method] | |
| 5639 | ✗ | << " is specified explicitly."; | |
| 5640 | } | ||
| 5641 | } | ||
| 5642 | } | ||
| 5643 | |||
| 5644 | 9726 | srv_unix_file_flush_method = | |
| 5645 | 9726 | static_cast<srv_unix_flush_t>(innodb_flush_method); | |
| 5646 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | ut_ad(innodb_flush_method <= SRV_UNIX_O_DIRECT_NO_FSYNC); |
| 5647 | #else | ||
| 5648 | srv_win_file_flush_method = static_cast<srv_win_flush_t>(innodb_flush_method); | ||
| 5649 | ut_ad(innodb_flush_method <= SRV_WIN_IO_NORMAL); | ||
| 5650 | if (srv_use_native_aio) { | ||
| 5651 | ib::info(ER_IB_MSG_541) << "Using Windows native AIO"; | ||
| 5652 | } | ||
| 5653 | #endif /* !_WIN32 */ | ||
| 5654 | |||
| 5655 | #ifdef WITH_WSREP | ||
| 5656 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (innobase_disallow_writes) { |
| 5657 | ✗ | ib::warn() << "innodb_disallow_writes has been deprecated and" | |
| 5658 | " will be removed in future release." | ||
| 5659 | ✗ | " Consider using read_only instead."; | |
| 5660 | } | ||
| 5661 | #endif /* WITH_WSREP */ | ||
| 5662 | |||
| 5663 | /* Set the maximum number of threads which can wait for a semaphore | ||
| 5664 | inside InnoDB: this is the 'sync wait array' size, as well as the | ||
| 5665 | maximum number of threads that can wait in the 'srv_conc array' for | ||
| 5666 | their time to enter InnoDB. */ | ||
| 5667 | 9726 | srv_max_n_threads = 100 * 1024; | |
| 5668 | |||
| 5669 | /* This is the first time univ_page_size is used. | ||
| 5670 | It was initialized to 16k pages before srv_page_size was set */ | ||
| 5671 |
2/4✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9726 times.
✗ Branch 3 not taken.
|
9726 | univ_page_size.copy_from(page_size_t(srv_page_size, srv_page_size, false)); |
| 5672 | |||
| 5673 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | srv_sys_space.set_space_id(TRX_SYS_SPACE); |
| 5674 | |||
| 5675 | /* Create the filespace flags. */ | ||
| 5676 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | predefined_flags = fsp_flags_init(univ_page_size, false, false, true, false); |
| 5677 | 9726 | fsp_flags_set_sdi(predefined_flags); | |
| 5678 | |||
| 5679 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | srv_sys_space.set_flags(predefined_flags); |
| 5680 | |||
| 5681 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | srv_sys_space.set_name(dict_sys_t::s_sys_space_name); |
| 5682 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | srv_sys_space.set_path(srv_data_home); |
| 5683 | |||
| 5684 | /* We set the temporary tablspace id later, after recovery. | ||
| 5685 | The temp tablespace doesn't support raw devices. | ||
| 5686 | Set the name and path. */ | ||
| 5687 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | srv_tmp_space.set_name(dict_sys_t::s_temp_space_name); |
| 5688 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | srv_tmp_space.set_path(srv_data_home); |
| 5689 | |||
| 5690 | /* Create the filespace flags with the temp flag set. */ | ||
| 5691 | uint32_t fsp_flags = | ||
| 5692 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | fsp_flags_init(univ_page_size, false, false, false, true); |
| 5693 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | srv_tmp_space.set_flags(fsp_flags); |
| 5694 | |||
| 5695 | /* Set buffer pool size to default for fast startup when mysqld is | ||
| 5696 | run with --help --verbose options. */ | ||
| 5697 | 9726 | ulint srv_buf_pool_size_org = 0; | |
| 5698 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
9726 | if (opt_help && opt_verbose && opt_validate_config && |
| 5699 | ✗ | srv_buf_pool_size > srv_buf_pool_def_size) { | |
| 5700 | ✗ | ib::warn(ER_IB_MSG_543) << "Setting innodb_buf_pool_size to " | |
| 5701 | ✗ | << srv_buf_pool_def_size << " for fast startup, " | |
| 5702 | ✗ | << "when running with --help --verbose options."; | |
| 5703 | ✗ | srv_buf_pool_size_org = srv_buf_pool_size; | |
| 5704 | ✗ | srv_buf_pool_size = srv_buf_pool_def_size; | |
| 5705 | } | ||
| 5706 | |||
| 5707 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | innodb_buffer_pool_size_init(); |
| 5708 | |||
| 5709 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | innodb_undo_tablespaces_deprecate(); |
| 5710 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | innodb_parallel_doublewrite_path_deprecate(); |
| 5711 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | innodb_parallel_dblwr_encrypt_deprecate(); |
| 5712 | |||
| 5713 |
1/2✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
|
9726 | innodb_redo_log_capacity_init(); |
| 5714 | |||
| 5715 | /* Set the original value back to show in help. */ | ||
| 5716 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
|
9726 | if (srv_buf_pool_size_org != 0) { |
| 5717 | ✗ | srv_buf_pool_size_org = buf_pool_size_align(srv_buf_pool_size_org); | |
| 5718 | ✗ | srv_buf_pool_curr_size = srv_buf_pool_size_org; | |
| 5719 | } | ||
| 5720 | |||
| 5721 |
2/2✓ Branch 0 taken 9713 times.
✓ Branch 1 taken 13 times.
|
9726 | if (srv_n_page_cleaners > srv_buf_pool_instances) { |
| 5722 | /* limit of page_cleaner parallelizability | ||
| 5723 | is number of buffer pool instances. */ | ||
| 5724 | 9713 | srv_n_page_cleaners = srv_buf_pool_instances; | |
| 5725 | } | ||
| 5726 | |||
| 5727 | 9726 | srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE); | |
| 5728 | |||
| 5729 | 9726 | return 0; | |
| 5730 | 9733 | } | |
| 5731 | |||
| 5732 | 9693 | long innobase_get_open_files_limit() { return innobase_open_files; } | |
| 5733 | 12 | void innobase_set_open_files_limit(long new_limit) { | |
| 5734 | 12 | innobase_open_files = new_limit; | |
| 5735 | 12 | } | |
| 5736 | |||
| 5737 | /** Perform post-commit/rollback cleanup after DDL statement | ||
| 5738 | @param[in,out] thd connection thread */ | ||
| 5739 | 327376 | static void innobase_post_ddl(THD *thd) { | |
| 5740 | /* During upgrade, etc., the log_ddl may haven't been | ||
| 5741 | initialized and there is nothing to do now. */ | ||
| 5742 |
2/2✓ Branch 0 taken 317754 times.
✓ Branch 1 taken 9622 times.
|
327376 | if (log_ddl != nullptr) { |
| 5743 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 317755 times.
|
317754 | DBUG_EXECUTE_IF("DDL_Log_remove_inject_startup_error_3", |
| 5744 | srv_inject_too_many_concurrent_trxs = true;); | ||
| 5745 | |||
| 5746 | 317755 | dberr_t err = log_ddl->post_ddl(thd); | |
| 5747 | |||
| 5748 | /* If this fails, do not continue startup. */ | ||
| 5749 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 317665 times.
|
317665 | if (err != DB_SUCCESS) { |
| 5750 | ✗ | ib::fatal(UT_LOCATION_HERE, ER_IB_MSG_DDL_LOG_FAIL_POST_DDL); | |
| 5751 | } | ||
| 5752 | } | ||
| 5753 | 327287 | } | |
| 5754 | |||
| 5755 | /** Initialize the InnoDB storage engine plugin. | ||
| 5756 | @param[in,out] p InnoDB handlerton | ||
| 5757 | @return error code | ||
| 5758 | @retval 0 on success */ | ||
| 5759 | 9734 | static int innodb_init(void *p) { | |
| 5760 |
1/2✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
|
9734 | DBUG_TRACE; |
| 5761 | |||
| 5762 |
1/2✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
|
9734 | acquire_plugin_services(); |
| 5763 | |||
| 5764 | 9734 | handlerton *innobase_hton = (handlerton *)p; | |
| 5765 | 9734 | innodb_hton_ptr = innobase_hton; | |
| 5766 | |||
| 5767 | 9734 | innobase_hton->state = SHOW_OPTION_YES; | |
| 5768 | 9734 | innobase_hton->db_type = DB_TYPE_INNODB; | |
| 5769 | 9734 | innobase_hton->savepoint_offset = sizeof(trx_named_savept_t); | |
| 5770 | 9734 | innobase_hton->close_connection = innobase_close_connection; | |
| 5771 | 9734 | innobase_hton->kill_connection = innobase_kill_connection; | |
| 5772 | 9734 | innobase_hton->savepoint_set = innobase_savepoint; | |
| 5773 | 9734 | innobase_hton->savepoint_rollback = innobase_rollback_to_savepoint; | |
| 5774 | |||
| 5775 | 9734 | innobase_hton->savepoint_rollback_can_release_mdl = | |
| 5776 | innobase_rollback_to_savepoint_can_release_mdl; | ||
| 5777 | |||
| 5778 | 9734 | innobase_hton->savepoint_release = innobase_release_savepoint; | |
| 5779 | 9734 | innobase_hton->commit = innobase_commit; | |
| 5780 | 9734 | innobase_hton->rollback = innobase_rollback; | |
| 5781 | 9734 | innobase_hton->prepare = innobase_xa_prepare; | |
| 5782 | 9734 | innobase_hton->recover = innobase_xa_recover; | |
| 5783 | 9734 | innobase_hton->recover_prepared_in_tc = innobase_xa_recover_prepared_in_tc; | |
| 5784 | 9734 | innobase_hton->commit_by_xid = innobase_commit_by_xid; | |
| 5785 | 9734 | innobase_hton->rollback_by_xid = innobase_rollback_by_xid; | |
| 5786 | 9734 | innobase_hton->set_prepared_in_tc = innobase_set_prepared_in_tc; | |
| 5787 | 9734 | innobase_hton->set_prepared_in_tc_by_xid = innobase_set_prepared_in_tc_by_xid; | |
| 5788 | 9734 | innobase_hton->create = innobase_create_handler; | |
| 5789 | 9734 | innobase_hton->is_valid_tablespace_name = innobase_is_valid_tablespace_name; | |
| 5790 | 9734 | innobase_hton->alter_tablespace = innobase_alter_tablespace; | |
| 5791 | 9734 | innobase_hton->get_tablespace_filename_ext = | |
| 5792 | innobase_get_tablespace_filename_ext; | ||
| 5793 | 9734 | innobase_hton->upgrade_tablespace = dd_upgrade_tablespace; | |
| 5794 | 9734 | innobase_hton->upgrade_space_version = upgrade_space_version; | |
| 5795 | 9734 | innobase_hton->upgrade_logs = dd_upgrade_logs; | |
| 5796 | 9734 | innobase_hton->finish_upgrade = dd_upgrade_finish; | |
| 5797 | 9734 | innobase_hton->pre_dd_shutdown = innodb_pre_dd_shutdown; | |
| 5798 | 9734 | innobase_hton->panic = innodb_shutdown; | |
| 5799 | 9734 | innobase_hton->partition_flags = innobase_partition_flags; | |
| 5800 | |||
| 5801 | 9734 | innobase_hton->start_consistent_snapshot = | |
| 5802 | innobase_start_trx_and_assign_read_view; | ||
| 5803 | 9734 | innobase_hton->clone_consistent_snapshot = | |
| 5804 | innobase_start_trx_and_clone_read_view; | ||
| 5805 | |||
| 5806 | 9734 | innobase_hton->store_binlog_info = innobase_store_binlog_info; | |
| 5807 | |||
| 5808 | 9734 | innobase_hton->flush_logs = innobase_flush_logs; | |
| 5809 | 9734 | innobase_hton->show_status = innobase_show_status; | |
| 5810 | 9734 | innobase_hton->lock_hton_log = innobase_lock_hton_log; | |
| 5811 | 9734 | innobase_hton->unlock_hton_log = innobase_unlock_hton_log; | |
| 5812 | 9734 | innobase_hton->collect_hton_log_info = innobase_collect_hton_log_info; | |
| 5813 | 9734 | innobase_hton->fill_is_table = innobase_fill_i_s_table; | |
| 5814 | 9734 | innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS | | |
| 5815 | HTON_SUPPORTS_FOREIGN_KEYS | HTON_SUPPORTS_ATOMIC_DDL | | ||
| 5816 | HTON_CAN_RECREATE | HTON_SUPPORTS_SECONDARY_ENGINE | | ||
| 5817 | HTON_SUPPORTS_TABLE_ENCRYPTION | | ||
| 5818 | HTON_SUPPORTS_ONLINE_BACKUPS | HTON_SUPPORTS_COMPRESSED_COLUMNS | | ||
| 5819 | HTON_SUPPORTS_GENERATED_INVISIBLE_PK; | ||
| 5820 | #ifdef WITH_WSREP | ||
| 5821 | 9734 | innobase_hton->flags |= HTON_WSREP_REPLICATION; | |
| 5822 | #endif /* WITH_WSREP */ | ||
| 5823 | |||
| 5824 | 9734 | innobase_hton->replace_native_transaction_in_thd = innodb_replace_trx_in_thd; | |
| 5825 | 9734 | innobase_hton->file_extensions = ha_innobase_exts; | |
| 5826 | 9734 | innobase_hton->data = &innodb_api_cb; | |
| 5827 | 9734 | innobase_hton->ddse_dict_init = innobase_ddse_dict_init; | |
| 5828 | |||
| 5829 | 9734 | innobase_hton->dict_register_dd_table_id = innobase_dict_register_dd_table_id; | |
| 5830 | |||
| 5831 | 9734 | innobase_hton->dict_cache_reset = innobase_dict_cache_reset; | |
| 5832 | 9734 | innobase_hton->dict_cache_reset_tables_and_tablespaces = | |
| 5833 | innobase_dict_cache_reset_tables_and_tablespaces; | ||
| 5834 | |||
| 5835 | 9734 | innobase_hton->dict_recover = innobase_dict_recover; | |
| 5836 | 9734 | innobase_hton->dict_get_server_version = innobase_dict_get_server_version; | |
| 5837 | 9734 | innobase_hton->dict_set_server_version = innobase_dict_set_server_version; | |
| 5838 | |||
| 5839 | 9734 | innobase_hton->post_recover = innobase_post_recover; | |
| 5840 | |||
| 5841 | 9734 | innobase_hton->is_supported_system_table = innobase_is_supported_system_table; | |
| 5842 | |||
| 5843 | 9734 | innobase_hton->get_table_statistics = innobase_get_table_statistics; | |
| 5844 | |||
| 5845 | 9734 | innobase_hton->get_index_column_cardinality = | |
| 5846 | innobase_get_index_column_cardinality; | ||
| 5847 | |||
| 5848 | 9734 | innobase_hton->get_tablespace_statistics = innobase_get_tablespace_statistics; | |
| 5849 | 9734 | innobase_hton->get_tablespace_type = innobase_get_tablespace_type; | |
| 5850 | 9734 | innobase_hton->get_tablespace_type_by_name = | |
| 5851 | innobase_get_tablespace_type_by_name; | ||
| 5852 | |||
| 5853 | 9734 | innobase_hton->is_tablespace_keyring_pre_v3_encrypted = | |
| 5854 | innobase_is_tablespace_keyring_pre_v3_encrypted; | ||
| 5855 | |||
| 5856 | 9734 | innobase_hton->is_dict_readonly = innobase_is_dict_readonly; | |
| 5857 | |||
| 5858 | 9734 | innobase_hton->sdi_create = dict_sdi_create; | |
| 5859 | 9734 | innobase_hton->sdi_drop = dict_sdi_drop; | |
| 5860 | 9734 | innobase_hton->sdi_get_keys = dict_sdi_get_keys; | |
| 5861 | 9734 | innobase_hton->sdi_get = dict_sdi_get; | |
| 5862 | 9734 | innobase_hton->sdi_set = dict_sdi_set; | |
| 5863 | 9734 | innobase_hton->sdi_delete = dict_sdi_delete; | |
| 5864 | |||
| 5865 | 9734 | innobase_hton->rotate_encryption_master_key = | |
| 5866 | innobase_encryption_key_rotation; | ||
| 5867 | |||
| 5868 | 9734 | innobase_hton->fix_tablespaces_empty_uuid = | |
| 5869 | innobase_fix_tablespaces_empty_uuid; | ||
| 5870 | |||
| 5871 | 9734 | innobase_hton->fix_default_table_encryption = | |
| 5872 | innobase_fix_default_table_encryption; | ||
| 5873 | |||
| 5874 | 9734 | innobase_hton->redo_log_set_state = innobase_redo_set_state; | |
| 5875 | |||
| 5876 | 9734 | innobase_hton->post_ddl = innobase_post_ddl; | |
| 5877 | |||
| 5878 | #ifdef WITH_WSREP | ||
| 5879 | 9734 | innobase_hton->wsrep_abort_transaction = wsrep_abort_transaction_func; | |
| 5880 | 9734 | innobase_hton->wsrep_set_checkpoint = innobase_wsrep_set_checkpoint; | |
| 5881 | 9734 | innobase_hton->wsrep_get_checkpoint = innobase_wsrep_get_checkpoint; | |
| 5882 | |||
| 5883 | 9734 | bool wsrep_provider_loaded = | |
| 5884 |
3/4✓ Branch 0 taken 9734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 453 times.
✓ Branch 3 taken 9281 times.
|
9734 | !(strlen(wsrep_provider) == 0 || !strcmp(wsrep_provider, WSREP_NONE)); |
| 5885 | |||
| 5886 | /* innodb_autoinc_lock_mode (recommended value = Interleaved/2) */ | ||
| 5887 |
2/2✓ Branch 0 taken 453 times.
✓ Branch 1 taken 9281 times.
|
9734 | if (wsrep_provider_loaded && |
| 5888 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 452 times.
|
453 | innobase_autoinc_lock_mode != AUTOINC_NO_LOCKING) { |
| 5889 |
1/3✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | switch (pxc_strict_mode) { |
| 5890 | ✗ | case PXC_STRICT_MODE_DISABLED: | |
| 5891 | ✗ | break; | |
| 5892 | ✗ | case PXC_STRICT_MODE_PERMISSIVE: | |
| 5893 | ✗ | WSREP_WARN( | |
| 5894 | "Percona-XtraDB-Cluster doesn't recommend" | ||
| 5895 | " setting innodb_autoinc_lock_mode to" | ||
| 5896 | " TRADITIONAL/CONSECUTIVE" | ||
| 5897 | " with pxc_strict_mode = PERMISSIVE"); | ||
| 5898 | ✗ | break; | |
| 5899 | 1 | case PXC_STRICT_MODE_ENFORCING: | |
| 5900 | case PXC_STRICT_MODE_MASTER: | ||
| 5901 | default: | ||
| 5902 |
14/28✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
|
1 | WSREP_ERROR( |
| 5903 | "Percona-XtraDB-Cluster prohibits" | ||
| 5904 | " setting innodb_autoinc_lock_mode to" | ||
| 5905 | " TRADITIONAL/CONSECUTIVE" | ||
| 5906 | " with pxc_strict_mode = ENFORCING" | ||
| 5907 | " or MASTER"); | ||
| 5908 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return (innodb_init_abort()); |
| 5909 | break; | ||
| 5910 | } | ||
| 5911 | } | ||
| 5912 | #endif /* WITH_WSREP */ | ||
| 5913 | |||
| 5914 | /* Initialize handler clone interfaces for. */ | ||
| 5915 | |||
| 5916 | 9733 | innobase_hton->clone_interface.clone_capability = innodb_clone_get_capability; | |
| 5917 | 9733 | innobase_hton->clone_interface.clone_begin = innodb_clone_begin; | |
| 5918 | 9733 | innobase_hton->clone_interface.clone_copy = innodb_clone_copy; | |
| 5919 | 9733 | innobase_hton->clone_interface.clone_ack = innodb_clone_ack; | |
| 5920 | 9733 | innobase_hton->clone_interface.clone_end = innodb_clone_end; | |
| 5921 | |||
| 5922 | 9733 | innobase_hton->clone_interface.clone_apply_begin = innodb_clone_apply_begin; | |
| 5923 | 9733 | innobase_hton->clone_interface.clone_apply = innodb_clone_apply; | |
| 5924 | 9733 | innobase_hton->clone_interface.clone_apply_end = innodb_clone_apply_end; | |
| 5925 | |||
| 5926 | 9733 | innobase_hton->foreign_keys_flags = | |
| 5927 | HTON_FKS_WITH_PREFIX_PARENT_KEYS | | ||
| 5928 | HTON_FKS_NEED_DIFFERENT_PARENT_AND_SUPPORTING_KEYS | | ||
| 5929 | HTON_FKS_WITH_EXTENDED_PARENT_KEYS; | ||
| 5930 | |||
| 5931 | 9733 | innobase_hton->check_fk_column_compat = innodb_check_fk_column_compat; | |
| 5932 | 9733 | innobase_hton->fk_name_suffix = {STRING_WITH_LEN("_ibfk_")}; | |
| 5933 | |||
| 5934 | 9733 | innobase_hton->is_reserved_db_name = innobase_check_reserved_file_name; | |
| 5935 | |||
| 5936 | 9733 | innobase_hton->page_track.start = innobase_page_track_start; | |
| 5937 | 9733 | innobase_hton->page_track.stop = innobase_page_track_stop; | |
| 5938 | 9733 | innobase_hton->page_track.purge = innobase_page_track_purge; | |
| 5939 | 9733 | innobase_hton->page_track.get_page_ids = innobase_page_track_get_page_ids; | |
| 5940 | 9733 | innobase_hton->page_track.get_num_page_ids = | |
| 5941 | innobase_page_track_get_num_page_ids; | ||
| 5942 | 9733 | innobase_hton->page_track.get_status = innobase_page_track_get_status; | |
| 5943 | |||
| 5944 | 9733 | innobase_hton->upgrade_get_compression_dict_data = | |
| 5945 | dd_upgrade_get_compression_dict_data; | ||
| 5946 | |||
| 5947 | static_assert(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); | ||
| 5948 | |||
| 5949 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | os_file_set_umask(my_umask); |
| 5950 | |||
| 5951 | /* Setup the memory alloc/free tracing mechanisms before calling | ||
| 5952 | any functions that could possibly allocate memory. */ | ||
| 5953 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | ut_new_boot(); |
| 5954 | |||
| 5955 | #ifdef HAVE_PSI_INTERFACE | ||
| 5956 | /* Register keys with MySQL performance schema */ | ||
| 5957 | int count; | ||
| 5958 | |||
| 5959 | #ifdef UNIV_DEBUG | ||
| 5960 | /** Count of Performance Schema keys that have been registered. */ | ||
| 5961 | 9733 | int global_count = 0; | |
| 5962 | #endif /* UNIV_DEBUG */ | ||
| 5963 | |||
| 5964 | 9733 | count = static_cast<int>(array_elements(all_pthread_mutexes)); | |
| 5965 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | mysql_mutex_register("innodb", all_pthread_mutexes, count); |
| 5966 | |||
| 5967 | #ifdef UNIV_DEBUG | ||
| 5968 | 9733 | global_count += count; | |
| 5969 | #endif /* UNIV_DEBUG */ | ||
| 5970 | |||
| 5971 | #ifdef UNIV_PFS_MEMORY | ||
| 5972 | 9733 | count = static_cast<int>(array_elements(pfs_instrumented_innodb_memory)); | |
| 5973 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | mysql_memory_register("innodb", pfs_instrumented_innodb_memory, count); |
| 5974 | #endif /* UNIV_PFS_MEMORY */ | ||
| 5975 | |||
| 5976 | #ifdef UNIV_PFS_MUTEX | ||
| 5977 | 9733 | count = static_cast<int>(array_elements(all_innodb_mutexes)); | |
| 5978 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | mysql_mutex_register("innodb", all_innodb_mutexes, count); |
| 5979 | |||
| 5980 | #ifdef UNIV_DEBUG | ||
| 5981 | 9733 | global_count += count; | |
| 5982 | #endif /* UNIV_DEBUG */ | ||
| 5983 | |||
| 5984 | #endif /* UNIV_PFS_MUTEX */ | ||
| 5985 | |||
| 5986 | #ifdef UNIV_PFS_RWLOCK | ||
| 5987 | 9733 | count = static_cast<int>(array_elements(all_innodb_rwlocks)); | |
| 5988 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | mysql_rwlock_register("innodb", all_innodb_rwlocks, count); |
| 5989 | |||
| 5990 | #ifdef UNIV_DEBUG | ||
| 5991 | 9733 | global_count += count; | |
| 5992 | #endif /* UNIV_DEBUG */ | ||
| 5993 | |||
| 5994 | #endif /* UNIV_PFS_MUTEX */ | ||
| 5995 | |||
| 5996 | #ifdef UNIV_PFS_THREAD | ||
| 5997 | 9733 | count = static_cast<int>(array_elements(all_innodb_threads)); | |
| 5998 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | mysql_thread_register("innodb", all_innodb_threads, count); |
| 5999 | |||
| 6000 | #ifdef UNIV_DEBUG | ||
| 6001 | 9733 | global_count += count; | |
| 6002 | #endif /* UNIV_DEBUG */ | ||
| 6003 | |||
| 6004 | #endif /* UNIV_PFS_THREAD */ | ||
| 6005 | |||
| 6006 | #ifdef UNIV_PFS_IO | ||
| 6007 | 9733 | count = static_cast<int>(array_elements(all_innodb_files)); | |
| 6008 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | mysql_file_register("innodb", all_innodb_files, count); |
| 6009 | |||
| 6010 | #ifdef UNIV_DEBUG | ||
| 6011 | 9733 | global_count += count; | |
| 6012 | #endif /* UNIV_DEBUG */ | ||
| 6013 | |||
| 6014 | #endif /* UNIV_PFS_IO */ | ||
| 6015 | |||
| 6016 | 9733 | count = static_cast<int>(array_elements(all_innodb_conds)); | |
| 6017 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | mysql_cond_register("innodb", all_innodb_conds, count); |
| 6018 | |||
| 6019 | #ifdef UNIV_DEBUG | ||
| 6020 | 9733 | global_count += count; | |
| 6021 | #endif /* UNIV_DEBUG */ | ||
| 6022 | |||
| 6023 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | mysql_data_lock_register(&innodb_data_lock_inspector); |
| 6024 | |||
| 6025 | #ifdef UNIV_DEBUG | ||
| 6026 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9733 times.
|
9733 | if (mysql_pfs_key_t::get_count() != global_count) { |
| 6027 | ✗ | ib::error(ER_IB_MSG_544) << "You have created new InnoDB PFS key(s) but " | |
| 6028 | ✗ | << mysql_pfs_key_t::get_count() - global_count | |
| 6029 | ✗ | << " key(s) is/are not registered with PFS. Please" | |
| 6030 | ✗ | << " register the keys in PFS arrays in" | |
| 6031 | ✗ | << " ha_innodb.cc."; | |
| 6032 | |||
| 6033 | ✗ | return HA_ERR_INITIALIZATION; | |
| 6034 | } | ||
| 6035 | #endif /* UNIV_DEBUG */ | ||
| 6036 | |||
| 6037 | #endif /* HAVE_PSI_INTERFACE */ | ||
| 6038 | |||
| 6039 |
1/2✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
|
9733 | os_event_global_init(); |
| 6040 | |||
| 6041 |
3/4✓ Branch 0 taken 9733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 9726 times.
|
9733 | if (innodb_init_params()) { |
| 6042 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | return innodb_init_abort(); |
| 6043 | } | ||
| 6044 | |||
| 6045 | /* After this point, error handling has to use | ||
| 6046 | innodb_init_abort(). */ | ||
| 6047 | |||
| 6048 | /* Initialize component service handles */ | ||
| 6049 |
2/4✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
|
9726 | if (innobase::component_services::intitialize_service_handles() == false) { |
| 6050 | ✗ | return innodb_init_abort(); | |
| 6051 | } | ||
| 6052 | |||
| 6053 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 9726 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
|
9726 | if (srv_default_table_encryption == DEFAULT_TABLE_ENC_ONLINE_TO_KEYRING && |
| 6054 | ✗ | !Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist( | |
| 6055 | FIL_DEFAULT_ENCRYPTION_KEY, server_uuid)) { | ||
| 6056 | ✗ | sql_print_error( | |
| 6057 | "InnoDB: cannot enable encryption, innodb_encrypt_tables is set to " | ||
| 6058 | "value different than OFF, but " | ||
| 6059 | "keyring plugin is not available"); | ||
| 6060 | ✗ | return innodb_init_abort(); | |
| 6061 | } | ||
| 6062 | |||
| 6063 | // We are starting encryption threads, we must lock the keyring plugins | ||
| 6064 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9724 times.
|
9726 | if (srv_n_fil_crypt_threads_requested > 0) { |
| 6065 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | uint number_of_keyring_locked = lock_keyrings(nullptr); |
| 6066 | |||
| 6067 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (number_of_keyring_locked == 0) { |
| 6068 | ✗ | sql_print_error( | |
| 6069 | "InnoDB: cannot enable encryption threads, " | ||
| 6070 | "keyring plugin is not available"); | ||
| 6071 | |||
| 6072 | ✗ | return innodb_init_abort(); | |
| 6073 | } | ||
| 6074 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (Encryption::is_keyring_alive() == false) { |
| 6075 | ✗ | sql_print_error( | |
| 6076 | "InnoDB: keyring plugin is installed but it seems it was not " | ||
| 6077 | "properly initialized. Cannot enable encryption threads."); | ||
| 6078 | ✗ | unlock_keyrings(nullptr); | |
| 6079 | |||
| 6080 | ✗ | return innodb_init_abort(); | |
| 6081 | } | ||
| 6082 | } | ||
| 6083 | |||
| 6084 |
2/4✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9726 times.
|
9726 | if (!srv_sys_space.parse_params(innobase_data_file_path, true)) { |
| 6085 | ✗ | ib::error(ER_IB_MSG_545) | |
| 6086 | ✗ | << "Unable to parse innodb_data_file_path=" << innobase_data_file_path; | |
| 6087 | ✗ | return innodb_init_abort(); | |
| 6088 | } | ||
| 6089 | |||
| 6090 |
3/4✓ Branch 0 taken 9726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 9723 times.
|
9726 | if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false)) { |
| 6091 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | ib::error(ER_IB_MSG_546) << "Unable to parse innodb_temp_data_file_path=" |
| 6092 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | << innobase_temp_data_file_path; |
| 6093 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | return innodb_init_abort(); |
| 6094 | } | ||
| 6095 | |||
| 6096 | /* Perform all sanity check before we take action of deleting files*/ | ||
| 6097 |
3/4✓ Branch 0 taken 9723 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 9722 times.
|
9723 | if (srv_sys_space.intersection(&srv_tmp_space)) { |
| 6098 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | log_errlog(ERROR_LEVEL, ER_INNODB_FILES_SAME, srv_tmp_space.name(), |
| 6099 | srv_sys_space.name()); | ||
| 6100 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return innodb_init_abort(); |
| 6101 | } | ||
| 6102 | |||
| 6103 | /* Check for keyring plugin if UNDO/REDO logs are intended to be encrypted */ | ||
| 6104 |
6/6✓ Branch 0 taken 9680 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 9643 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 9717 times.
|
9801 | if ((srv_undo_log_encrypt || srv_redo_log_encrypt) && |
| 6105 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 74 times.
|
79 | Encryption::check_keyring() == false) { |
| 6106 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | return innodb_init_abort(); |
| 6107 | } | ||
| 6108 | |||
| 6109 | 9717 | return 0; | |
| 6110 | 9734 | } | |
| 6111 | |||
| 6112 | /** De initialize the InnoDB storage engine plugin. */ | ||
| 6113 | 8361 | static int innodb_deinit(MYSQL_PLUGIN plugin_info [[maybe_unused]]) { | |
| 6114 | 8361 | release_plugin_services(); | |
| 6115 | 8361 | return 0; | |
| 6116 | } | ||
| 6117 | |||
| 6118 | /** Create a hard-coded tablespace file at server initialization. | ||
| 6119 | @param[in] space_id fil_space_t::id | ||
| 6120 | @param[in] filename file name | ||
| 6121 | @param[in] flags tabelspace flags | ||
| 6122 | @retval false on success | ||
| 6123 | @retval true on failure */ | ||
| 6124 | 283 | static bool dd_create_hardcoded(space_id_t space_id, const char *filename, | |
| 6125 | ulint flags) { | ||
| 6126 | 283 | page_no_t pages = FIL_IBD_FILE_INITIAL_SIZE; | |
| 6127 | |||
| 6128 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | dberr_t err = fil_ibd_create(space_id, dict_sys_t::s_dd_space_name, filename, |
| 6129 | flags, pages, FIL_ENCRYPTION_DEFAULT, | ||
| 6130 | 283 | KeyringEncryptionKeyIdInfo()); | |
| 6131 | |||
| 6132 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | if (err == DB_SUCCESS) { |
| 6133 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | mtr_t mtr; |
| 6134 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | mtr.start(); |
| 6135 | |||
| 6136 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | bool ret = fsp_header_init(space_id, pages, &mtr); |
| 6137 | |||
| 6138 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | mtr.commit(); |
| 6139 | |||
| 6140 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | if (ret) { |
| 6141 |
1/2✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
|
283 | btr_sdi_create_index(space_id, false); |
| 6142 | 283 | return (false); | |
| 6143 | } | ||
| 6144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 283 times.
|
283 | } |
| 6145 | |||
| 6146 | ✗ | return (true); | |
| 6147 | } | ||
| 6148 | |||
| 6149 | /** Open a hard-coded tablespace file at server initialization. | ||
| 6150 | @param[in] space_id fil_space_t::id | ||
| 6151 | @param[in] filename file name | ||
| 6152 | @param[in] flags tabelspace flags | ||
| 6153 | @retval false on success | ||
| 6154 | @retval true on failure */ | ||
| 6155 | 9339 | static bool dd_open_hardcoded(space_id_t space_id, const char *filename, | |
| 6156 | ulint flags) { | ||
| 6157 | 9339 | bool fail = false; | |
| 6158 |
1/2✓ Branch 0 taken 9339 times.
✗ Branch 1 not taken.
|
9339 | fil_space_t *space = fil_space_acquire_silent(space_id); |
| 6159 | 9339 | Keyring_encryption_info keyring_encryption_info; | |
| 6160 | |||
| 6161 |
2/2✓ Branch 0 taken 1730 times.
✓ Branch 1 taken 7609 times.
|
9339 | if (space != nullptr) { |
| 6162 | /* ADD SDI flag presence in predefined flags of mysql | ||
| 6163 | tablespace. */ | ||
| 6164 | |||
| 6165 |
2/4✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1730 times.
✗ Branch 3 not taken.
|
3460 | if (strstr(space->files.front().name, filename) != nullptr && |
| 6166 | /* Ignore encryption flag as it might have changed */ | ||
| 6167 |
1/2✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
|
1730 | !((space->flags ^ flags) & ~(FSP_FLAGS_MASK_ENCRYPTION))) { |
| 6168 |
1/2✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
|
1730 | fil_space_open_if_needed(space); |
| 6169 | |||
| 6170 | } else { | ||
| 6171 | ✗ | fail = true; | |
| 6172 | } | ||
| 6173 | |||
| 6174 |
1/2✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
|
1730 | fil_space_release(space); |
| 6175 | |||
| 6176 |
1/2✓ Branch 0 taken 7609 times.
✗ Branch 1 not taken.
|
7609 | } else if (fil_ibd_open(true, FIL_TYPE_TABLESPACE, space_id, flags, |
| 6177 | dict_sys_t::s_dd_space_name, filename, true, | ||
| 6178 |
1/2✓ Branch 0 taken 7609 times.
✗ Branch 1 not taken.
|
7609 | false, keyring_encryption_info) == DB_SUCCESS) { |
| 6179 | /* Set fil_space_t::size, which is 0 initially. */ | ||
| 6180 |
1/2✓ Branch 0 taken 7609 times.
✗ Branch 1 not taken.
|
7609 | ulint size = fil_space_get_size(space_id); |
| 6181 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7609 times.
|
7609 | ut_a(size != ULINT_UNDEFINED); |
| 6182 | |||
| 6183 | } else { | ||
| 6184 | ✗ | fail = true; | |
| 6185 | } | ||
| 6186 | |||
| 6187 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9339 times.
|
9339 | if (fail) { |
| 6188 | ✗ | my_error(ER_CANT_OPEN_FILE, MYF(0), filename, 0, ""); | |
| 6189 | } | ||
| 6190 | |||
| 6191 | 9339 | return (fail); | |
| 6192 | } | ||
| 6193 | |||
| 6194 | /** Open or create InnoDB data files. | ||
| 6195 | @param[in] dict_init_mode whether to create or open the files | ||
| 6196 | @param[in,out] tablespaces predefined tablespaces created by the DDSE | ||
| 6197 | @return 0 on success, 1 on failure */ | ||
| 6198 | 9707 | static int innobase_init_files(dict_init_mode_t dict_init_mode, | |
| 6199 | List<const Plugin_tablespace> *tablespaces, | ||
| 6200 | bool &is_dd_encrypted) { | ||
| 6201 |
1/2✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
|
9707 | DBUG_TRACE; |
| 6202 | |||
| 6203 |
6/8✓ Branch 0 taken 9501 times.
✓ Branch 1 taken 206 times.
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 9391 times.
✓ Branch 4 taken 110 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9707 times.
|
9707 | ut_ad(dict_init_mode == DICT_INIT_CREATE_FILES || |
| 6204 | dict_init_mode == DICT_INIT_CHECK_FILES || | ||
| 6205 | dict_init_mode == DICT_INIT_UPGRADE_57_FILES); | ||
| 6206 | |||
| 6207 | 9707 | bool create = (dict_init_mode == DICT_INIT_CREATE_FILES); | |
| 6208 | |||
| 6209 | /* Check if the data files exist or not. */ | ||
| 6210 | dberr_t err = | ||
| 6211 |
1/2✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
|
9707 | srv_sys_space.check_file_spec(create, MIN_EXPECTED_TABLESPACE_SIZE); |
| 6212 | |||
| 6213 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9703 times.
|
9707 | if (err != DB_SUCCESS) { |
| 6214 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | return innodb_init_abort(); |
| 6215 | } | ||
| 6216 | |||
| 6217 | 9703 | srv_is_upgrade_mode = (dict_init_mode == DICT_INIT_UPGRADE_57_FILES); | |
| 6218 | |||
| 6219 | /* Start the InnoDB server. */ | ||
| 6220 |
1/2✓ Branch 0 taken 9702 times.
✗ Branch 1 not taken.
|
9703 | err = srv_start(create); |
| 6221 | |||
| 6222 |
2/2✓ Branch 0 taken 80 times.
✓ Branch 1 taken 9622 times.
|
9702 | if (err != DB_SUCCESS) { |
| 6223 |
1/2✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
|
80 | return innodb_init_abort(); |
| 6224 | } | ||
| 6225 | |||
| 6226 | 9622 | space_id_t upgrade_mysql_plugin_space = SPACE_UNKNOWN; | |
| 6227 | |||
| 6228 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 9541 times.
|
9622 | if (srv_is_upgrade_mode) { |
| 6229 |
2/4✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
|
81 | if (!dict_sys_table_id_build()) { |
| 6230 | ✗ | return innodb_init_abort(); | |
| 6231 | } | ||
| 6232 | |||
| 6233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
|
81 | if (trx_sys->found_prepared_trx) { |
| 6234 | ✗ | ib::error(ER_DD_UPGRADE_FOUND_PREPARED_XA_TRANSACTION); | |
| 6235 | ✗ | return innodb_init_abort(); | |
| 6236 | } | ||
| 6237 | |||
| 6238 | /* Disable AHI when we start loading tables for purge. | ||
| 6239 | These tables are evicted anyway after purge. */ | ||
| 6240 | |||
| 6241 | 81 | bool old_btr_search_value = btr_search_enabled; | |
| 6242 | 81 | btr_search_enabled = false; | |
| 6243 | |||
| 6244 | /* Load all tablespaces upfront from InnoDB Dictionary. | ||
| 6245 | This is needed for applying purge and ibuf from 5.7 */ | ||
| 6246 |
2/4✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
|
81 | if (dict_load_tablespaces_for_upgrade()) { |
| 6247 | // there is a keyring v1 encrypted table - fail the upgrade | ||
| 6248 | ✗ | ib::error(ER_UPGRADE_KEYRING_UNSUPPORTED_VERSION_ENCRYPTION); | |
| 6249 | ✗ | return innodb_init_abort(); | |
| 6250 | } | ||
| 6251 | |||
| 6252 | /* Start purge threads immediately and wait for purge to | ||
| 6253 | become empty. All table_ids will be adjusted by a fixed | ||
| 6254 | offset during upgrade. So purge cannot load a table by | ||
| 6255 | table_id later. Also InnoDB dictionary will be dropped | ||
| 6256 | during the process of upgrade. So apply all the purge | ||
| 6257 | now. */ | ||
| 6258 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | srv_start_purge_threads(); |
| 6259 | |||
| 6260 | uint64_t rseg_history_len; | ||
| 6261 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 81 times.
|
170 | while ((rseg_history_len = trx_sys->rseg_history_len.load()) != 0) { |
| 6262 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
8 | ib::info(ER_IB_MSG_547) |
| 6263 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | << "Waiting for purge to become empty:" |
| 6264 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | << " current purge history len is " << rseg_history_len; |
| 6265 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | sleep(1); |
| 6266 | } | ||
| 6267 | |||
| 6268 | 81 | srv_upgrade_old_undo_found = false; | |
| 6269 | |||
| 6270 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | buf_flush_sync_all_buf_pools(); |
| 6271 | |||
| 6272 | /* We have to find the space_id of "mysql/plugin" here. i.e. before we evict | ||
| 6273 | the tables from cache. */ | ||
| 6274 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | dict_table_t *table = dict_table_open_on_name("mysql/plugin", false, true, |
| 6275 | DICT_ERR_IGNORE_NONE); | ||
| 6276 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | if (table != nullptr) { |
| 6277 | 81 | upgrade_mysql_plugin_space = table->space; | |
| 6278 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | dict_table_close(table, false, false); |
| 6279 | } | ||
| 6280 | |||
| 6281 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | dict_upgrade_evict_tables_cache(); |
| 6282 | |||
| 6283 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | dict_stats_evict_tablespaces(); |
| 6284 | |||
| 6285 | 81 | btr_search_enabled = old_btr_search_value; | |
| 6286 | } | ||
| 6287 | |||
| 6288 | 9622 | bool do_encrypt = false; | |
| 6289 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | bool ret = dict_detect_encryption_of_mysql_ibd( |
| 6290 | dict_init_mode, upgrade_mysql_plugin_space, do_encrypt); | ||
| 6291 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9622 times.
|
9622 | if (!ret) { |
| 6292 | ✗ | ib::error(ER_XB_MSG_4, "mysql.ibd") | |
| 6293 | << "Failed to determine if mysql.ibd is encrypted. " | ||
| 6294 | ✗ | "Have you deleted it?"; | |
| 6295 | ✗ | return innodb_init_abort(); | |
| 6296 | } | ||
| 6297 | |||
| 6298 |
4/6✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9602 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9622 times.
|
9622 | if (do_encrypt && !Encryption::check_keyring()) { |
| 6299 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 6300 | ✗ | return innodb_init_abort(); | |
| 6301 | } | ||
| 6302 | |||
| 6303 | 9622 | is_dd_encrypted = do_encrypt; | |
| 6304 | |||
| 6305 | 9622 | const ulint dd_space_flags = | |
| 6306 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9602 times.
|
9622 | do_encrypt ? predefined_flags | FSP_FLAGS_MASK_ENCRYPTION |
| 6307 | : predefined_flags; | ||
| 6308 | |||
| 6309 | // For upgrade from 5.7, create mysql.ibd | ||
| 6310 | 9622 | create |= (dict_init_mode == DICT_INIT_UPGRADE_57_FILES); | |
| 6311 |
3/4✓ Branch 0 taken 283 times.
✓ Branch 1 taken 9339 times.
✓ Branch 2 taken 283 times.
✗ Branch 3 not taken.
|
9622 | ret = create ? dd_create_hardcoded(dict_sys_t::s_dict_space_id, |
| 6312 | dict_sys_t::s_dd_space_file_name, | ||
| 6313 | dd_space_flags) | ||
| 6314 |
1/2✓ Branch 0 taken 9339 times.
✗ Branch 1 not taken.
|
9339 | : dd_open_hardcoded(dict_sys_t::s_dict_space_id, |
| 6315 | dict_sys_t::s_dd_space_file_name, | ||
| 6316 | dd_space_flags); | ||
| 6317 | |||
| 6318 | /* Once hardcoded tablespace mysql is created or opened, | ||
| 6319 | prepare it along with innodb system tablespace for server. | ||
| 6320 | Tell server that these two hardcoded tablespaces exist. */ | ||
| 6321 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | if (!ret) { |
| 6322 | 9622 | const size_t len = | |
| 6323 | 30 + sizeof("id=;flags=;server_version=;space_version=;state=normal"); | ||
| 6324 | 9622 | const char *fmt = | |
| 6325 | "id=%u;flags=%u;server_version=%u;space_version=%u;state=normal"; | ||
| 6326 | static char se_private_data_innodb_system[len]; | ||
| 6327 | static char se_private_data_dd[len]; | ||
| 6328 | 9622 | snprintf(se_private_data_innodb_system, len, fmt, TRX_SYS_SPACE, | |
| 6329 | srv_sys_space.flags(), DD_SPACE_CURRENT_SRV_VERSION, | ||
| 6330 | DD_SPACE_CURRENT_SPACE_VERSION); | ||
| 6331 | |||
| 6332 | 9622 | snprintf(se_private_data_dd, len, fmt, dict_sys_t::s_dict_space_id, | |
| 6333 | dd_space_flags, DD_SPACE_CURRENT_SRV_VERSION, | ||
| 6334 | DD_SPACE_CURRENT_SPACE_VERSION); | ||
| 6335 | |||
| 6336 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9602 times.
|
9622 | const char *dd_space_options = do_encrypt ? "encryption=y" : ""; |
| 6337 | |||
| 6338 | static Plugin_tablespace dd_space(dict_sys_t::s_dd_space_name, | ||
| 6339 | dd_space_options, se_private_data_dd, "", | ||
| 6340 |
3/8✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
9622 | innobase_hton_name); |
| 6341 | static Plugin_tablespace::Plugin_tablespace_file dd_file( | ||
| 6342 |
2/4✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
|
9622 | dict_sys_t::s_dd_space_file_name, ""); |
| 6343 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | dd_space.add_file(&dd_file); |
| 6344 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | tablespaces->push_back(&dd_space); |
| 6345 | |||
| 6346 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9618 times.
|
9622 | const char *options = srv_sys_space.is_encrypted() ? "encryption=y" : ""; |
| 6347 | |||
| 6348 | static Plugin_tablespace innodb(dict_sys_t::s_sys_space_name, options, | ||
| 6349 | se_private_data_innodb_system, "", | ||
| 6350 |
3/8✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
9622 | innobase_hton_name); |
| 6351 | 9622 | Tablespace::files_t::const_iterator end = srv_sys_space.m_files.end(); | |
| 6352 | 9622 | Tablespace::files_t::const_iterator begin = srv_sys_space.m_files.begin(); | |
| 6353 |
2/2✓ Branch 0 taken 9650 times.
✓ Branch 1 taken 9622 times.
|
19272 | for (Tablespace::files_t::const_iterator it = begin; it != end; ++it) { |
| 6354 | 9650 | innobase_sys_files.push_back( | |
| 6355 |
2/4✓ Branch 0 taken 9650 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9650 times.
✗ Branch 3 not taken.
|
9650 | ut::new_withkey<Plugin_tablespace::Plugin_tablespace_file>( |
| 6356 | 9650 | UT_NEW_THIS_FILE_PSI_KEY, it->name(), "")); | |
| 6357 |
1/2✓ Branch 0 taken 9650 times.
✗ Branch 1 not taken.
|
9650 | innodb.add_file(innobase_sys_files.back()); |
| 6358 | } | ||
| 6359 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | tablespaces->push_back(&innodb); |
| 6360 | |||
| 6361 | } else { | ||
| 6362 | ✗ | return innodb_init_abort(); | |
| 6363 | } | ||
| 6364 | |||
| 6365 | 9622 | innobase_old_blocks_pct = static_cast<uint>( | |
| 6366 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | buf_LRU_old_ratio_update(innobase_old_blocks_pct, true)); |
| 6367 | |||
| 6368 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | ibuf_max_size_update(srv_change_buffer_max_size); |
| 6369 | |||
| 6370 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | innobase_open_tables = ut::new_<hash_table_t>(200); |
| 6371 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | mysql_mutex_init(innobase_share_mutex_key.m_value, &innobase_share_mutex, |
| 6372 | MY_MUTEX_INIT_FAST); | ||
| 6373 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | mysql_mutex_init(commit_cond_mutex_key.m_value, &commit_cond_m, |
| 6374 | MY_MUTEX_INIT_FAST); | ||
| 6375 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | mysql_cond_init(commit_cond_key.m_value, &commit_cond); |
| 6376 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | mysql_mutex_init(resume_encryption_cond_mutex_key.m_value, |
| 6377 | &resume_encryption_cond_m, MY_MUTEX_INIT_FAST); | ||
| 6378 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | mysql_cond_init(resume_encryption_cond_key.m_value, &resume_encryption_cond); |
| 6379 | 9622 | innodb_inited = true; | |
| 6380 | #ifdef MYSQL_DYNAMIC_PLUGIN | ||
| 6381 | if (innobase_hton != p) { | ||
| 6382 | innobase_hton = reinterpret_cast<handlerton *>(p); | ||
| 6383 | *innobase_hton = *innodb_hton_ptr; | ||
| 6384 | } | ||
| 6385 | #endif /* MYSQL_DYNAMIC_PLUGIN */ | ||
| 6386 | |||
| 6387 | /* Do this as late as possible so server is fully starts up, | ||
| 6388 | since we might get some initial stats if user choose to turn | ||
| 6389 | on some counters from start up */ | ||
| 6390 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9620 times.
|
9622 | if (innobase_enable_monitor_counter) { |
| 6391 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | innodb_enable_monitor_at_startup(innobase_enable_monitor_counter); |
| 6392 | } | ||
| 6393 | |||
| 6394 | /* Turn on monitor counters that are default on */ | ||
| 6395 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | srv_mon_default_on(); |
| 6396 | |||
| 6397 | /* Unit Tests */ | ||
| 6398 | #ifdef UNIV_ENABLE_UNIT_TEST_GET_PARENT_DIR | ||
| 6399 | unit_test_os_file_get_parent_dir(); | ||
| 6400 | #endif /* UNIV_ENABLE_UNIT_TEST_GET_PARENT_DIR */ | ||
| 6401 | |||
| 6402 | #ifdef UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH | ||
| 6403 | test_make_filepath(); | ||
| 6404 | #endif /*UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH */ | ||
| 6405 | |||
| 6406 | #ifdef UNIV_ENABLE_DICT_STATS_TEST | ||
| 6407 | test_dict_stats_all(); | ||
| 6408 | #endif /*UNIV_ENABLE_DICT_STATS_TEST */ | ||
| 6409 | |||
| 6410 | #ifdef UNIV_ENABLE_UNIT_TEST_ROW_RAW_FORMAT_INT | ||
| 6411 | #ifdef HAVE_UT_CHRONO_T | ||
| 6412 | test_row_raw_format_int(); | ||
| 6413 | #endif /* HAVE_UT_CHRONO_T */ | ||
| 6414 | #endif /* UNIV_ENABLE_UNIT_TEST_ROW_RAW_FORMAT_INT */ | ||
| 6415 | |||
| 6416 | 9622 | return 0; | |
| 6417 | 9706 | } | |
| 6418 | |||
| 6419 | /** Flush InnoDB redo logs to the file system. | ||
| 6420 | @param[in] hton InnoDB handlerton | ||
| 6421 | @param[in] binlog_group_flush true if we got invoked by binlog | ||
| 6422 | group commit during flush stage, false in other cases. | ||
| 6423 | @return false */ | ||
| 6424 | 2583007 | static bool innobase_flush_logs(handlerton *hton, bool binlog_group_flush) { | |
| 6425 |
1/2✓ Branch 0 taken 2583026 times.
✗ Branch 1 not taken.
|
2583007 | DBUG_TRACE; |
| 6426 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2583026 times.
|
2583026 | assert(hton == innodb_hton_ptr); |
| 6427 | |||
| 6428 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2582994 times.
|
2583026 | if (srv_read_only_mode) { |
| 6429 | 32 | return false; | |
| 6430 | } | ||
| 6431 | |||
| 6432 | /* If !binlog_group_flush, we got invoked by FLUSH LOGS or similar. | ||
| 6433 | Else, we got invoked by binlog group commit during flush stage. */ | ||
| 6434 | |||
| 6435 |
4/4✓ Branch 0 taken 2497347 times.
✓ Branch 1 taken 85647 times.
✓ Branch 2 taken 33121 times.
✓ Branch 3 taken 2464226 times.
|
2582994 | if (binlog_group_flush && srv_flush_log_at_trx_commit == 0) { |
| 6436 | /* innodb_flush_log_at_trx_commit=0 | ||
| 6437 | (write and sync once per second). | ||
| 6438 | Do not flush the redo log during binlog group commit. */ | ||
| 6439 | |||
| 6440 | /* This could be unsafe if we grouped at least one DDL transaction, | ||
| 6441 | and we removed !trx->ddl_must_flush from condition which is checked | ||
| 6442 | inside trx_commit_complete_for_mysql() when we decide if we could | ||
| 6443 | skip the flush. */ | ||
| 6444 | 33121 | return false; | |
| 6445 | } | ||
| 6446 | |||
| 6447 | /* Signal and wait for all GTIDs to persist on disk. */ | ||
| 6448 |
2/2✓ Branch 0 taken 85650 times.
✓ Branch 1 taken 2464223 times.
|
2549873 | if (!binlog_group_flush) { |
| 6449 | 85650 | auto >id_persistor = clone_sys->get_gtid_persistor(); | |
| 6450 |
1/2✓ Branch 0 taken 85650 times.
✗ Branch 1 not taken.
|
85650 | gtid_persistor.wait_flush(true, true, nullptr); |
| 6451 | } | ||
| 6452 | |||
| 6453 | /* Flush the redo log buffer to the redo log file. | ||
| 6454 | Sync it to disc if we are in FLUSH LOGS, or if | ||
| 6455 | innodb_flush_log_at_trx_commit=1 | ||
| 6456 | (write and sync at each commit). */ | ||
| 6457 |
3/4✓ Branch 0 taken 2464226 times.
✓ Branch 1 taken 85647 times.
✓ Branch 2 taken 2549837 times.
✗ Branch 3 not taken.
|
5014099 | log_buffer_flush_to_disk(!binlog_group_flush || |
| 6458 |
2/2✓ Branch 0 taken 2424069 times.
✓ Branch 1 taken 40157 times.
|
2464226 | srv_flush_log_at_trx_commit == 1); |
| 6459 | |||
| 6460 | 2549837 | return false; | |
| 6461 | 2582990 | } | |
| 6462 | |||
| 6463 | /** Commits a transaction in an InnoDB database. */ | ||
| 6464 | 20743612 | void innobase_commit_low(trx_t *trx) /*!< in: transaction handle */ | |
| 6465 | { | ||
| 6466 | #ifdef WITH_WSREP | ||
| 6467 | 20743612 | THD *thd = (THD *)trx->mysql_thd; | |
| 6468 |
2/2✓ Branch 0 taken 557638 times.
✓ Branch 1 taken 20186022 times.
|
20743612 | if (wsrep_on(thd)) { |
| 6469 | char info[64]; | ||
| 6470 | 557638 | info[sizeof(info) - 1] = '\0'; | |
| 6471 |
1/2✓ Branch 0 taken 557640 times.
✗ Branch 1 not taken.
|
557638 | snprintf(info, sizeof(info) - 1, "innobase_commit_low (%lld)", |
| 6472 | (long long)wsrep_thd_trx_seqno(thd)); | ||
| 6473 |
1/2✓ Branch 0 taken 557639 times.
✗ Branch 1 not taken.
|
557640 | wsrep_set_thd_proc_info(thd, info); |
| 6474 |
2/4✓ Branch 0 taken 557639 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 557640 times.
✗ Branch 3 not taken.
|
557639 | thd_proc_info(thd, wsrep_get_thd_proc_info(thd)); |
| 6475 | } | ||
| 6476 | #endif /* WITH_WSREP */ | ||
| 6477 | |||
| 6478 |
2/2✓ Branch 0 taken 19807382 times.
✓ Branch 1 taken 936280 times.
|
20743662 | DEBUG_SYNC_C("innobase_commit_low_begin"); |
| 6479 | |||
| 6480 |
2/2✓ Branch 0 taken 16605301 times.
✓ Branch 1 taken 4138384 times.
|
20743697 | if (trx_is_started(trx)) { |
| 6481 | 16605301 | const dberr_t error [[maybe_unused]] = trx_commit_for_mysql(trx); | |
| 6482 | #ifdef WITH_WSREP | ||
| 6483 | // The original comment is not necessarily true for PXC. | ||
| 6484 | // We removed check for TRX_FORCE_ROLLBACK_DISABLE from 'if' condition in | ||
| 6485 | // lock_make_trx_hit_list(), so now HP transaction can BF other transaction | ||
| 6486 | // even if the flag is set. | ||
| 6487 | // It is OK in general case if local transaction is not empty (so it is | ||
| 6488 | // replicated and certified). If it conflicts with HP transaction it will | ||
| 6489 | // not be certified (so will be discarded), and if it was certified, there | ||
| 6490 | // is no possibility for other transaction to BF it because that other | ||
| 6491 | // transaction should fail certification. | ||
| 6492 | // If local transaction is the empty transaction, it is not replicated | ||
| 6493 | // and certified as it does not generate any writestes. So it follows the | ||
| 6494 | // normal transaction path. But empty transaction can get some locks. | ||
| 6495 | // If at the same time there is replicated transaction attempting to get the | ||
| 6496 | // same locks, it can BF local transaction at any stage, even if local | ||
| 6497 | // transaction is commiting. (note that it can happen only for empty local | ||
| 6498 | // transaction) | ||
| 6499 |
5/8✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16605280 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 16605270 times.
|
16605281 | ut_ad(DB_SUCCESS == error || |
| 6500 | (DB_FORCED_ABORT == error && thd->wsrep_trx().is_empty())); | ||
| 6501 | #else | ||
| 6502 | // This is ut_ad not ut_a, because previously we did not have an assert | ||
| 6503 | // and nobody has noticed for a long time, so probably there is no much | ||
| 6504 | // harm in silencing this error. OTOH we believe it should no longer happen | ||
| 6505 | // after adding `true` as a second argument to TrxInInnoDB constructor call, | ||
| 6506 | // so we'd like to learn if the error can still happen. | ||
| 6507 | ut_ad(DB_SUCCESS == error); | ||
| 6508 | #endif | ||
| 6509 | } | ||
| 6510 | 20743654 | trx->will_lock = 0; | |
| 6511 | 20743654 | } | |
| 6512 | |||
| 6513 | /** Stores the current binlog coordinates in the trx system header | ||
| 6514 | @param[in] hton InnoDB handlerton | ||
| 6515 | @param[in] thd MySQL thread handle */ | ||
| 6516 | 249 | static int innobase_store_binlog_info(handlerton *hton, THD *thd) noexcept { | |
| 6517 | 249 | DBUG_ENTER("innobase_store_binlog_info"); | |
| 6518 | |||
| 6519 | const char *file_name; | ||
| 6520 | unsigned long long pos; | ||
| 6521 | 249 | thd_binlog_pos(thd, &file_name, &pos); | |
| 6522 | |||
| 6523 | 249 | trx_sys_write_binlog_position("", std::numeric_limits<uint64_t>::max(), | |
| 6524 | file_name, pos); | ||
| 6525 | |||
| 6526 | 249 | innobase_flush_logs(hton, false); | |
| 6527 | |||
| 6528 | 249 | DBUG_RETURN(0); | |
| 6529 | } | ||
| 6530 | |||
| 6531 | /** Creates an InnoDB transaction struct for the thd if it does not yet have | ||
| 6532 | one. Starts a new InnoDB transaction if a transaction is not yet started. And | ||
| 6533 | assigns a new snapshot for a consistent read if the transaction does not yet | ||
| 6534 | have one. | ||
| 6535 | @return 0 */ | ||
| 6536 | 64 | static int innobase_start_trx_and_assign_read_view( | |
| 6537 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 6538 | THD *thd) /*!< in: MySQL thread handle of the user for | ||
| 6539 | whom the transaction should be committed */ | ||
| 6540 | { | ||
| 6541 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | DBUG_TRACE; |
| 6542 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
|
64 | assert(hton == innodb_hton_ptr); |
| 6543 | |||
| 6544 | /* Create a new trx struct for thd, if it does not yet have one */ | ||
| 6545 | |||
| 6546 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | trx_t *trx = check_trx_exists(thd); |
| 6547 | |||
| 6548 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | TrxInInnoDB trx_in_innodb(trx); |
| 6549 | |||
| 6550 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | innobase_srv_conc_force_exit_innodb(trx); |
| 6551 | |||
| 6552 | /* The transaction should not be active yet, start it */ | ||
| 6553 |
2/4✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
|
64 | ut_ad(!trx_is_started(trx)); |
| 6554 | |||
| 6555 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE); |
| 6556 | |||
| 6557 | /* Assign a read view if the transaction does not have it yet. | ||
| 6558 | Do this only if transaction is using REPEATABLE READ isolation | ||
| 6559 | level. */ | ||
| 6560 | 64 | trx->isolation_level = | |
| 6561 |
2/4✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
|
64 | innobase_trx_map_isolation_level(thd_get_trx_isolation(thd)); |
| 6562 | |||
| 6563 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) { |
| 6564 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | trx_assign_read_view(trx); |
| 6565 | } else { | ||
| 6566 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, | |
| 6567 | "InnoDB: WITH CONSISTENT SNAPSHOT" | ||
| 6568 | " was ignored because this phrase" | ||
| 6569 | " can only be used with" | ||
| 6570 | " REPEATABLE READ isolation level."); | ||
| 6571 | } | ||
| 6572 | |||
| 6573 | /* Set the MySQL flag to mark that there is an active transaction */ | ||
| 6574 | |||
| 6575 |
2/4✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
|
64 | innobase_register_trx(hton, current_thd, trx); |
| 6576 | |||
| 6577 | 64 | return 0; | |
| 6578 | 64 | } | |
| 6579 | |||
| 6580 | /** Creates an InnoDB transaction struct for the thd if it does not | ||
| 6581 | yet have one. Starts a new InnoDB transaction if a transaction is not | ||
| 6582 | yet started. And clones snapshot for a consistent read from another | ||
| 6583 | session, if it has one. | ||
| 6584 | @param[in] hton InnoDB handlerton | ||
| 6585 | @param[in] thd MySQL thread handle of the user for whom the | ||
| 6586 | transaction should be committed | ||
| 6587 | @param[in] from_thd MySQL thread handle of the user session from | ||
| 6588 | which the consistent read should be cloned | ||
| 6589 | @return 0 */ | ||
| 6590 | 21 | static int innobase_start_trx_and_clone_read_view(handlerton *hton, THD *thd, | |
| 6591 | THD *from_thd) { | ||
| 6592 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | DBUG_ENTER("innobase_start_trx_and_clone_read_view"); |
| 6593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | assert(hton == innodb_hton_ptr); |
| 6594 | |||
| 6595 | /* Get transaction handle from the donor session */ | ||
| 6596 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | trx_t *const from_trx = thd_to_trx(from_thd); |
| 6597 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | if (!from_trx) { |
| 6598 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, | |
| 6599 | "InnoDB: WITH CONSISTENT SNAPSHOT FROM SESSION was " | ||
| 6600 | "ignored because the specified session does not have " | ||
| 6601 | "an open transaction inside InnoDB."); | ||
| 6602 | |||
| 6603 | ✗ | DBUG_RETURN(0); | |
| 6604 | } | ||
| 6605 | |||
| 6606 | /* Create a new trx struct for thd, if it does not yet have one */ | ||
| 6607 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | trx_t *const trx = check_trx_exists(thd); |
| 6608 | |||
| 6609 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | innobase_srv_conc_force_exit_innodb(trx); |
| 6610 | |||
| 6611 | /* If the transaction is not started yet, start it */ | ||
| 6612 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE); |
| 6613 | |||
| 6614 | /* Clone the read view from the donor transaction. Do this only if | ||
| 6615 | transaction is using REPEATABLE READ isolation level. */ | ||
| 6616 | 21 | trx->isolation_level = | |
| 6617 |
2/4✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
|
21 | innobase_trx_map_isolation_level(thd_get_trx_isolation(thd)); |
| 6618 | |||
| 6619 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
|
21 | if (trx->isolation_level != TRX_ISO_REPEATABLE_READ) { |
| 6620 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 6621 | "InnoDB: WITH CONSISTENT SNAPSHOT was ignored because " | ||
| 6622 | "this phrase can only be used with REPEATABLE READ " | ||
| 6623 | "isolation level."); | ||
| 6624 | } else { | ||
| 6625 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | locksys::Global_exclusive_latch_guard guard{UT_LOCATION_HERE}; |
| 6626 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | trx_sys_mutex_enter(); |
| 6627 |
4/8✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
|
20 | trx_mutex_enter(from_trx); |
| 6628 |
3/4✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 17 times.
|
20 | if (!trx_clone_read_view(trx, from_trx)) { |
| 6629 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 6630 | "InnoDB: WITH CONSISTENT SNAPSHOT FROM SESSION was " | ||
| 6631 | "ignored because the target transaction has not " | ||
| 6632 | "been assigned a read view."); | ||
| 6633 | } | ||
| 6634 | 20 | } | |
| 6635 | |||
| 6636 | /* Set the MySQL flag to mark that there is an active transaction */ | ||
| 6637 |
2/4✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
|
21 | innobase_register_trx(hton, current_thd, trx); |
| 6638 | |||
| 6639 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | DBUG_RETURN(0); |
| 6640 | } | ||
| 6641 | |||
| 6642 | /** Commits a transaction in an InnoDB database or marks an SQL statement | ||
| 6643 | ended. | ||
| 6644 | @return 0 or deadlock error if the transaction was aborted by another | ||
| 6645 | higher priority transaction. */ | ||
| 6646 | 28233157 | static int innobase_commit(handlerton *hton, /*!< in: InnoDB handlerton */ | |
| 6647 | THD *thd, /*!< in: MySQL thread handle of the | ||
| 6648 | user for whom the transaction should | ||
| 6649 | be committed */ | ||
| 6650 | bool commit_trx) /*!< in: true - commit transaction | ||
| 6651 | false - the current SQL statement | ||
| 6652 | ended */ | ||
| 6653 | { | ||
| 6654 |
1/2✓ Branch 0 taken 28233295 times.
✗ Branch 1 not taken.
|
28233157 | DBUG_TRACE; |
| 6655 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28233295 times.
|
28233295 | assert(hton == innodb_hton_ptr); |
| 6656 |
5/8✓ Branch 0 taken 28233292 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28233289 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1413 times.
✓ Branch 5 taken 28231876 times.
✓ Branch 6 taken 1413 times.
✗ Branch 7 not taken.
|
28233295 | DBUG_PRINT("trans", ("ending transaction")); |
| 6657 |
3/4✓ Branch 0 taken 25332987 times.
✓ Branch 1 taken 2900302 times.
✓ Branch 2 taken 25333069 times.
✗ Branch 3 not taken.
|
28233289 | DEBUG_SYNC_C("transaction_commit_start"); |
| 6658 | |||
| 6659 |
1/2✓ Branch 0 taken 28233299 times.
✗ Branch 1 not taken.
|
28233371 | trx_t *trx = check_trx_exists(thd); |
| 6660 | |||
| 6661 | /* We are about to check if the transaction is_aborted, and if it is, | ||
| 6662 | then we want to rollback, and otherwise we want to proceed. | ||
| 6663 | However it might happen that a different transaction, which has high priority | ||
| 6664 | will abort our transaction just after we do the test. | ||
| 6665 | To prevent that, we want to set TRX_FORCE_ROLLBACK_DISABLE flag on our trx, | ||
| 6666 | which is checked in RecLock::make_trx_hit_list and prevents high priority | ||
| 6667 | transaction from killing us. | ||
| 6668 | One way to do that is to call TrxInInnoDB with `true` as second argument. | ||
| 6669 | Note that innobase_commit is called not only on "real" COMMIT, but also | ||
| 6670 | after each statement (with commit_trx=false), so we need some logic to decide | ||
| 6671 | if we really plan to perform commit during this call. | ||
| 6672 | */ | ||
| 6673 | bool will_commit = | ||
| 6674 |
2/2✓ Branch 0 taken 26374594 times.
✓ Branch 1 taken 1858705 times.
|
54607907 | commit_trx || |
| 6675 |
3/4✓ Branch 0 taken 26374608 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18874460 times.
✓ Branch 3 taken 7500148 times.
|
26374594 | (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); |
| 6676 |
1/2✓ Branch 0 taken 28233279 times.
✗ Branch 1 not taken.
|
28233313 | TrxInInnoDB trx_in_innodb(trx, will_commit); |
| 6677 | |||
| 6678 |
3/4✓ Branch 0 taken 28233292 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 28233287 times.
|
28233279 | if (trx_in_innodb.is_aborted()) { |
| 6679 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | innobase_rollback(hton, thd, commit_trx); |
| 6680 | |||
| 6681 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd); |
| 6682 | } | ||
| 6683 | |||
| 6684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28233224 times.
|
28233287 | ut_ad(trx->dict_operation_lock_mode == 0); |
| 6685 | |||
| 6686 | /* Transaction is deregistered only in a commit or a rollback. If | ||
| 6687 | it is deregistered we know there cannot be resources to be freed | ||
| 6688 | and we could return immediately. For the time being, we play safe | ||
| 6689 | and do the cleanup though there should be nothing to clean up. */ | ||
| 6690 | |||
| 6691 |
5/8✓ Branch 0 taken 696219 times.
✓ Branch 1 taken 27536992 times.
✓ Branch 2 taken 696236 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 696236 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 28233228 times.
|
28233224 | if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) { |
| 6692 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE); | |
| 6693 | } | ||
| 6694 | |||
| 6695 |
4/4✓ Branch 0 taken 15674665 times.
✓ Branch 1 taken 12558578 times.
✓ Branch 2 taken 4742936 times.
✓ Branch 3 taken 10931729 times.
|
28233243 | bool read_only = trx->read_only || trx->id == 0; |
| 6696 | |||
| 6697 |
2/2✓ Branch 0 taken 20733121 times.
✓ Branch 1 taken 7500122 times.
|
28233243 | if (will_commit) { |
| 6698 |
4/6✓ Branch 0 taken 20733127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 20733124 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
20733121 | DBUG_EXECUTE_IF("crash_innodb_before_commit", DBUG_SUICIDE();); |
| 6699 | /* We were instructed to commit the whole transaction, or | ||
| 6700 | this is an SQL statement end and autocommit is on */ | ||
| 6701 | |||
| 6702 | /* We need current binlog position for mysqlbackup to work. */ | ||
| 6703 | |||
| 6704 |
2/2✓ Branch 0 taken 3507807 times.
✓ Branch 1 taken 17225317 times.
|
20733124 | if (!read_only) { |
| 6705 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3507789 times.
|
3507807 | while (innobase_commit_concurrency > 0) { |
| 6706 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | mysql_mutex_lock(&commit_cond_m); |
| 6707 | |||
| 6708 | 18 | ++commit_threads; | |
| 6709 | |||
| 6710 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (commit_threads <= innobase_commit_concurrency) { |
| 6711 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | mysql_mutex_unlock(&commit_cond_m); |
| 6712 | 18 | break; | |
| 6713 | } | ||
| 6714 | |||
| 6715 | ✗ | --commit_threads; | |
| 6716 | |||
| 6717 | ✗ | mysql_cond_wait(&commit_cond, &commit_cond_m); | |
| 6718 | |||
| 6719 | ✗ | mysql_mutex_unlock(&commit_cond_m); | |
| 6720 | } | ||
| 6721 | |||
| 6722 | /* The following call reads the binary log position of | ||
| 6723 | the transaction being committed. | ||
| 6724 | |||
| 6725 | Binary logging of other engines is not relevant to | ||
| 6726 | InnoDB as all InnoDB requires is that committing | ||
| 6727 | InnoDB transactions appear in the same order in the | ||
| 6728 | MySQL binary log as they appear in InnoDB logs, which | ||
| 6729 | is guaranteed by the server. | ||
| 6730 | |||
| 6731 | If the binary log is not enabled, or the transaction | ||
| 6732 | is not written to the binary log, the file name will | ||
| 6733 | be a NULL pointer. */ | ||
| 6734 | ulonglong pos; | ||
| 6735 | |||
| 6736 |
1/2✓ Branch 0 taken 3507811 times.
✗ Branch 1 not taken.
|
3507807 | thd_binlog_pos(thd, &trx->mysql_log_file_name, &pos); |
| 6737 | |||
| 6738 | 3507811 | trx->mysql_log_offset = static_cast<uint64_t>(pos); | |
| 6739 | |||
| 6740 | /* Don't do write + flush right now. For group commit | ||
| 6741 | to work we want to do the flush later. */ | ||
| 6742 | 3507811 | trx->flush_log_later = true; | |
| 6743 | } | ||
| 6744 | |||
| 6745 | #ifdef WITH_WSREP | ||
| 6746 | /* If the transaction is not run in 2pc, we must assign wsrep | ||
| 6747 | XID here in order to get it written in rollback segment. */ | ||
| 6748 |
3/4✓ Branch 0 taken 20733115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 557636 times.
✓ Branch 3 taken 20175479 times.
|
20733128 | if (wsrep_on(thd)) { |
| 6749 |
1/2✓ Branch 0 taken 557636 times.
✗ Branch 1 not taken.
|
557636 | thd_get_xid(thd, (MYSQL_XID *)trx->xid); |
| 6750 | } | ||
| 6751 | #endif /* WITH_WSREP */ | ||
| 6752 | |||
| 6753 | /* If SE needs to persist GTID we must have a transaction. */ | ||
| 6754 |
3/4✓ Branch 0 taken 20733125 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 218 times.
✓ Branch 3 taken 20732907 times.
|
20733115 | if (thd->se_persists_gtid_explicit()) { |
| 6755 |
1/2✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
|
218 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 6756 | } | ||
| 6757 | |||
| 6758 |
1/2✓ Branch 0 taken 20733105 times.
✗ Branch 1 not taken.
|
20733125 | innobase_commit_low(trx); |
| 6759 | |||
| 6760 |
2/2✓ Branch 0 taken 3507809 times.
✓ Branch 1 taken 17225296 times.
|
20733105 | if (!read_only) { |
| 6761 | 3507809 | trx->flush_log_later = false; | |
| 6762 | |||
| 6763 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3507791 times.
|
3507809 | if (innobase_commit_concurrency > 0) { |
| 6764 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | mysql_mutex_lock(&commit_cond_m); |
| 6765 | |||
| 6766 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | ut_ad(commit_threads > 0); |
| 6767 | 18 | --commit_threads; | |
| 6768 | |||
| 6769 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | mysql_cond_signal(&commit_cond); |
| 6770 | |||
| 6771 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | mysql_mutex_unlock(&commit_cond_m); |
| 6772 | } | ||
| 6773 | } | ||
| 6774 | |||
| 6775 | 20733105 | trx_deregister_from_2pc(trx); | |
| 6776 | |||
| 6777 | /* Now do a write + flush of logs. */ | ||
| 6778 |
2/2✓ Branch 0 taken 3507809 times.
✓ Branch 1 taken 17225261 times.
|
20733070 | if (!read_only) { |
| 6779 |
1/2✓ Branch 0 taken 3507380 times.
✗ Branch 1 not taken.
|
3507809 | trx_commit_complete_for_mysql(trx); |
| 6780 | } | ||
| 6781 | |||
| 6782 | } else { | ||
| 6783 | /* We just mark the SQL statement ended and do not do a | ||
| 6784 | transaction commit */ | ||
| 6785 | |||
| 6786 | /* If we had reserved the auto-inc lock for some | ||
| 6787 | table in this SQL statement we release it now */ | ||
| 6788 | |||
| 6789 |
2/2✓ Branch 0 taken 7423880 times.
✓ Branch 1 taken 76242 times.
|
7500122 | if (!read_only) { |
| 6790 |
1/2✓ Branch 0 taken 7423947 times.
✗ Branch 1 not taken.
|
7423880 | lock_unlock_table_autoinc(trx); |
| 6791 | } | ||
| 6792 | |||
| 6793 | /* Store the current undo_no of the transaction so that we | ||
| 6794 | know where to roll back if we have to roll back the next | ||
| 6795 | SQL statement */ | ||
| 6796 | |||
| 6797 |
1/2✓ Branch 0 taken 7500144 times.
✗ Branch 1 not taken.
|
7500189 | trx_mark_sql_stat_end(trx); |
| 6798 | } | ||
| 6799 | |||
| 6800 | /* Reset the number AUTO-INC rows required */ | ||
| 6801 | 28232785 | trx->n_autoinc_rows = 0; | |
| 6802 | |||
| 6803 | /* This is a statement level variable. */ | ||
| 6804 | 28232785 | trx->fts_next_doc_id = 0; | |
| 6805 | |||
| 6806 |
1/2✓ Branch 0 taken 28232828 times.
✗ Branch 1 not taken.
|
28232785 | innobase_srv_conc_force_exit_innodb(trx); |
| 6807 | |||
| 6808 | 28232828 | return 0; | |
| 6809 | 28232833 | } | |
| 6810 | |||
| 6811 | /** Rolls back a transaction or the latest SQL statement. | ||
| 6812 | @return 0 or error number */ | ||
| 6813 | 646949 | static int innobase_rollback(handlerton *hton, /*!< in: InnoDB handlerton */ | |
| 6814 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 6815 | of the user whose transaction should | ||
| 6816 | be rolled back */ | ||
| 6817 | bool rollback_trx) /*!< in: true - rollback entire | ||
| 6818 | transaction false - rollback the | ||
| 6819 | current statement only */ | ||
| 6820 | { | ||
| 6821 |
1/2✓ Branch 0 taken 646953 times.
✗ Branch 1 not taken.
|
646949 | DBUG_TRACE; |
| 6822 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 646953 times.
|
646953 | assert(hton == innodb_hton_ptr); |
| 6823 |
3/8✓ Branch 0 taken 646953 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 646954 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 646954 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
646953 | DBUG_PRINT("trans", ("aborting transaction")); |
| 6824 | |||
| 6825 |
1/2✓ Branch 0 taken 646953 times.
✗ Branch 1 not taken.
|
646954 | trx_t *trx = check_trx_exists(thd); |
| 6826 | |||
| 6827 |
1/2✓ Branch 0 taken 646952 times.
✗ Branch 1 not taken.
|
646953 | TrxInInnoDB trx_in_innodb(trx); |
| 6828 | |||
| 6829 |
6/10✓ Branch 0 taken 646950 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 646490 times.
✓ Branch 3 taken 460 times.
✓ Branch 4 taken 646491 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 646492 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 646951 times.
|
646952 | ut_ad(trx_in_innodb.is_aborted() || |
| 6830 | (trx->dict_operation_lock_mode == 0 && | ||
| 6831 | trx->dict_operation == TRX_DICT_OP_NONE)); | ||
| 6832 | |||
| 6833 |
1/2✓ Branch 0 taken 646953 times.
✗ Branch 1 not taken.
|
646951 | innobase_srv_conc_force_exit_innodb(trx); |
| 6834 | |||
| 6835 | /* Reset the number AUTO-INC rows required */ | ||
| 6836 | |||
| 6837 | 646953 | trx->n_autoinc_rows = 0; | |
| 6838 | |||
| 6839 | /* If we had reserved the auto-inc lock for some table (if | ||
| 6840 | we come here to roll back the latest SQL statement) we | ||
| 6841 | release it now before a possibly lengthy rollback */ | ||
| 6842 | |||
| 6843 |
3/4✓ Branch 0 taken 646954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 646494 times.
✓ Branch 3 taken 460 times.
|
646953 | if (!trx_in_innodb.is_aborted()) { |
| 6844 |
1/2✓ Branch 0 taken 646493 times.
✗ Branch 1 not taken.
|
646494 | lock_unlock_table_autoinc(trx); |
| 6845 | } | ||
| 6846 | |||
| 6847 | /* This is a statement level variable. */ | ||
| 6848 | |||
| 6849 | 646953 | trx->fts_next_doc_id = 0; | |
| 6850 | |||
| 6851 | dberr_t error; | ||
| 6852 | |||
| 6853 | #ifdef WITH_WSREP | ||
| 6854 | /* If trx was assigned wsrep XID in prepare phase and the | ||
| 6855 | trx is being rolled back due to BF abort, clear XID in order | ||
| 6856 | to avoid writing it to rollback segment out of order. The XID | ||
| 6857 | will be reassigned when the transaction is replayed. */ | ||
| 6858 |
7/8✓ Branch 0 taken 630110 times.
✓ Branch 1 taken 16844 times.
✓ Branch 2 taken 630111 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✓ Branch 5 taken 630040 times.
✓ Branch 6 taken 71 times.
✓ Branch 7 taken 646884 times.
|
646953 | if (trx->state != TRX_STATE_NOT_STARTED && wsrep_is_wsrep_xid(trx->xid)) { |
| 6859 | 71 | trx->xid->reset(); | |
| 6860 | } | ||
| 6861 | #endif /* WITH_WSREP */ | ||
| 6862 | |||
| 6863 |
4/4✓ Branch 0 taken 636797 times.
✓ Branch 1 taken 10158 times.
✓ Branch 2 taken 639728 times.
✓ Branch 3 taken 7227 times.
|
1283752 | if (rollback_trx || |
| 6864 |
3/4✓ Branch 0 taken 636797 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 629570 times.
✓ Branch 3 taken 7227 times.
|
636797 | !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { |
| 6865 |
1/2✓ Branch 0 taken 639715 times.
✗ Branch 1 not taken.
|
639728 | error = trx_rollback_for_mysql(trx); |
| 6866 | |||
| 6867 |
2/4✓ Branch 0 taken 639716 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 639716 times.
|
639715 | ut_ad(trx_can_be_handled_by_current_thread_or_is_hp_victim(trx)); |
| 6868 |
2/2✓ Branch 0 taken 461 times.
✓ Branch 1 taken 639255 times.
|
639716 | if (trx->state.load(std::memory_order_relaxed) == |
| 6869 | TRX_STATE_FORCED_ROLLBACK) { | ||
| 6870 | #ifdef UNIV_DEBUG | ||
| 6871 | char buffer[1024]; | ||
| 6872 | |||
| 6873 |
1/2✓ Branch 0 taken 461 times.
✗ Branch 1 not taken.
|
461 | ib::info(ER_IB_MSG_548) |
| 6874 |
1/2✓ Branch 0 taken 461 times.
✗ Branch 1 not taken.
|
461 | << "Forced rollback : " |
| 6875 |
2/4✓ Branch 0 taken 461 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 461 times.
✗ Branch 3 not taken.
|
461 | << thd_security_context(thd, buffer, sizeof(buffer), 512); |
| 6876 | #endif /* UNIV_DEBUG */ | ||
| 6877 | 461 | trx->state.store(TRX_STATE_NOT_STARTED, std::memory_order_relaxed); | |
| 6878 | } | ||
| 6879 | |||
| 6880 | 639716 | trx_deregister_from_2pc(trx); | |
| 6881 | |||
| 6882 | } else { | ||
| 6883 |
1/2✓ Branch 0 taken 7226 times.
✗ Branch 1 not taken.
|
7227 | error = trx_rollback_last_sql_stat_for_mysql(trx); |
| 6884 | } | ||
| 6885 | |||
| 6886 |
1/2✓ Branch 0 taken 646941 times.
✗ Branch 1 not taken.
|
1293883 | return convert_error_code_to_mysql(error, 0, trx->mysql_thd); |
| 6887 | 646941 | } | |
| 6888 | |||
| 6889 | /** Rolls back a transaction | ||
| 6890 | @return 0 or error number */ | ||
| 6891 | 15660341 | static int innobase_rollback_trx(trx_t *trx) /*!< in: transaction */ | |
| 6892 | { | ||
| 6893 | 15660341 | dberr_t error = DB_SUCCESS; | |
| 6894 | |||
| 6895 |
1/2✓ Branch 0 taken 15660814 times.
✗ Branch 1 not taken.
|
15660341 | DBUG_TRACE; |
| 6896 |
5/8✓ Branch 0 taken 15660602 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15660769 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1171 times.
✓ Branch 5 taken 15659598 times.
✓ Branch 6 taken 1171 times.
✗ Branch 7 not taken.
|
15660814 | DBUG_PRINT("trans", ("aborting transaction")); |
| 6897 | |||
| 6898 |
1/2✓ Branch 0 taken 15660610 times.
✗ Branch 1 not taken.
|
15660769 | innobase_srv_conc_force_exit_innodb(trx); |
| 6899 | |||
| 6900 | /* If we had reserved the auto-inc lock for some table (if | ||
| 6901 | we come here to roll back the latest SQL statement) we | ||
| 6902 | release it now before a possibly lengthy rollback */ | ||
| 6903 |
3/4✓ Branch 0 taken 15660715 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15660705 times.
✓ Branch 3 taken 10 times.
|
15660610 | if (!TrxInInnoDB::is_aborted(trx)) { |
| 6904 |
1/2✓ Branch 0 taken 15660835 times.
✗ Branch 1 not taken.
|
15660705 | lock_unlock_table_autoinc(trx); |
| 6905 | } | ||
| 6906 | |||
| 6907 |
2/2✓ Branch 0 taken 408 times.
✓ Branch 1 taken 15660482 times.
|
15660845 | if (trx_is_rseg_updated(trx)) { |
| 6908 |
1/2✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
|
408 | error = trx_rollback_for_mysql(trx); |
| 6909 | } else { | ||
| 6910 | 15660482 | trx->will_lock = 0; | |
| 6911 | } | ||
| 6912 | |||
| 6913 |
1/2✓ Branch 0 taken 15660766 times.
✗ Branch 1 not taken.
|
31321685 | return convert_error_code_to_mysql(error, 0, trx->mysql_thd); |
| 6914 | 15660766 | } | |
| 6915 | |||
| 6916 | /** Rolls back a transaction to a savepoint. | ||
| 6917 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 6918 | given name */ | ||
| 6919 | 4219 | static int innobase_rollback_to_savepoint( | |
| 6920 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 6921 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 6922 | of the user whose transaction should | ||
| 6923 | be rolled back to savepoint */ | ||
| 6924 | void *savepoint) /*!< in: savepoint data */ | ||
| 6925 | { | ||
| 6926 |
1/2✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
|
4219 | DBUG_TRACE; |
| 6927 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4219 times.
|
4219 | assert(hton == innodb_hton_ptr); |
| 6928 | |||
| 6929 |
1/2✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
|
4219 | trx_t *trx = check_trx_exists(thd); |
| 6930 | |||
| 6931 |
1/2✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
|
4219 | TrxInInnoDB trx_in_innodb(trx); |
| 6932 | |||
| 6933 |
1/2✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
|
4219 | innobase_srv_conc_force_exit_innodb(trx); |
| 6934 | |||
| 6935 | /* TODO: use provided savepoint data area to store savepoint data */ | ||
| 6936 | |||
| 6937 | char name[64]; | ||
| 6938 | |||
| 6939 |
1/2✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
|
4219 | longlong2str((ulint)savepoint, name, 36); |
| 6940 | |||
| 6941 | int64_t mysql_binlog_cache_pos; | ||
| 6942 | |||
| 6943 | dberr_t error = | ||
| 6944 |
1/2✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
|
4219 | trx_rollback_to_savepoint_for_mysql(trx, name, &mysql_binlog_cache_pos); |
| 6945 | |||
| 6946 |
3/4✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 4202 times.
|
4219 | if (error == DB_SUCCESS && trx->fts_trx != nullptr) { |
| 6947 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | fts_savepoint_rollback(trx, name); |
| 6948 | } | ||
| 6949 | |||
| 6950 |
1/2✓ Branch 0 taken 4219 times.
✗ Branch 1 not taken.
|
8438 | return convert_error_code_to_mysql(error, 0, nullptr); |
| 6951 | 4219 | } | |
| 6952 | |||
| 6953 | /** Check whether innodb state allows to safely release MDL locks after | ||
| 6954 | rollback to savepoint. | ||
| 6955 | When binlog is on, MDL locks acquired after savepoint unit are not | ||
| 6956 | released if there are any locks held in InnoDB. | ||
| 6957 | @return true if it is safe, false if its not safe. */ | ||
| 6958 | 4204 | static bool innobase_rollback_to_savepoint_can_release_mdl( | |
| 6959 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 6960 | THD *thd) /*!< in: handle to the MySQL thread | ||
| 6961 | of the user whose transaction should | ||
| 6962 | be rolled back to savepoint */ | ||
| 6963 | { | ||
| 6964 |
1/2✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
|
4204 | DBUG_TRACE; |
| 6965 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4204 times.
|
4204 | assert(hton == innodb_hton_ptr); |
| 6966 | |||
| 6967 |
1/2✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
|
4204 | trx_t *trx = check_trx_exists(thd); |
| 6968 | |||
| 6969 |
1/2✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
|
4204 | TrxInInnoDB trx_in_innodb(trx); |
| 6970 | |||
| 6971 |
2/4✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4204 times.
|
4204 | ut_ad(thd == current_thd); |
| 6972 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4204 times.
|
4204 | ut_ad(trx->lock.wait_lock == nullptr); |
| 6973 |
1/2✓ Branch 0 taken 4204 times.
✗ Branch 1 not taken.
|
8408 | return UT_LIST_GET_LEN(trx->lock.trx_locks) == 0; |
| 6974 | 4204 | } | |
| 6975 | |||
| 6976 | /** Release transaction savepoint name. | ||
| 6977 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 6978 | given name */ | ||
| 6979 | 126 | static int innobase_release_savepoint( | |
| 6980 | handlerton *hton, /*!< in: handlerton for InnoDB */ | ||
| 6981 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 6982 | of the user whose transaction's | ||
| 6983 | savepoint should be released */ | ||
| 6984 | void *savepoint) /*!< in: savepoint data */ | ||
| 6985 | { | ||
| 6986 | dberr_t error; | ||
| 6987 | trx_t *trx; | ||
| 6988 | char name[64]; | ||
| 6989 | |||
| 6990 |
1/2✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
|
126 | DBUG_TRACE; |
| 6991 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
|
126 | assert(hton == innodb_hton_ptr); |
| 6992 | |||
| 6993 |
1/2✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
|
126 | trx = check_trx_exists(thd); |
| 6994 | |||
| 6995 |
1/2✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
|
126 | TrxInInnoDB trx_in_innodb(trx); |
| 6996 | |||
| 6997 | /* TODO: use provided savepoint data area to store savepoint data */ | ||
| 6998 | |||
| 6999 |
1/2✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
|
126 | longlong2str((ulint)savepoint, name, 36); |
| 7000 | |||
| 7001 |
1/2✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
|
126 | error = trx_release_savepoint_for_mysql(trx, name); |
| 7002 | |||
| 7003 |
3/4✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 114 times.
|
126 | if (error == DB_SUCCESS && trx->fts_trx != nullptr) { |
| 7004 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | fts_savepoint_release(trx, name); |
| 7005 | } | ||
| 7006 | |||
| 7007 |
1/2✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
|
252 | return convert_error_code_to_mysql(error, 0, nullptr); |
| 7008 | 126 | } | |
| 7009 | |||
| 7010 | /** Sets a transaction savepoint. | ||
| 7011 | @return always 0, that is, always succeeds */ | ||
| 7012 | 8201 | static int innobase_savepoint( | |
| 7013 | handlerton *hton, /*!< in: handle to the InnoDB handlerton */ | ||
| 7014 | THD *thd, /*!< in: handle to the MySQL thread */ | ||
| 7015 | void *savepoint) /*!< in: savepoint data */ | ||
| 7016 | { | ||
| 7017 |
1/2✓ Branch 0 taken 8202 times.
✗ Branch 1 not taken.
|
8201 | DBUG_TRACE; |
| 7018 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8202 times.
|
8202 | assert(hton == innodb_hton_ptr); |
| 7019 | |||
| 7020 | /* In the autocommit mode there is no sense to set a savepoint | ||
| 7021 | (unless we are in sub-statement), so SQL layer ensures that | ||
| 7022 | this method is never called in such situation. */ | ||
| 7023 | |||
| 7024 |
1/2✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
|
8202 | trx_t *trx = check_trx_exists(thd); |
| 7025 | |||
| 7026 |
1/2✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
|
8203 | TrxInInnoDB trx_in_innodb(trx); |
| 7027 | |||
| 7028 |
1/2✓ Branch 0 taken 8201 times.
✗ Branch 1 not taken.
|
8203 | innobase_srv_conc_force_exit_innodb(trx); |
| 7029 | |||
| 7030 | /* Cannot happen outside of transaction */ | ||
| 7031 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8203 times.
|
8201 | assert(trx_is_registered_for_2pc(trx)); |
| 7032 | |||
| 7033 | /* TODO: use provided savepoint data area to store savepoint data */ | ||
| 7034 | char name[64]; | ||
| 7035 | |||
| 7036 |
1/2✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
|
8203 | longlong2str((ulint)savepoint, name, 36); |
| 7037 | |||
| 7038 |
1/2✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
|
8203 | dberr_t error = trx_savepoint_for_mysql(trx, name, 0); |
| 7039 | |||
| 7040 |
3/4✓ Branch 0 taken 8203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 8151 times.
|
8203 | if (error == DB_SUCCESS && trx->fts_trx != nullptr) { |
| 7041 |
1/2✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
|
52 | fts_savepoint_take(trx->fts_trx, name); |
| 7042 | } | ||
| 7043 | |||
| 7044 |
1/2✓ Branch 0 taken 8202 times.
✗ Branch 1 not taken.
|
16406 | return convert_error_code_to_mysql(error, 0, nullptr); |
| 7045 | 8202 | } | |
| 7046 | |||
| 7047 | /** Frees a possible InnoDB trx object associated with the current THD. | ||
| 7048 | @return 0 or error number */ | ||
| 7049 | 15660708 | static int innobase_close_connection( | |
| 7050 | handlerton *hton, /*!< in: innobase handlerton */ | ||
| 7051 | THD *thd) /*!< in: handle to the MySQL thread of the user | ||
| 7052 | whose resources should be free'd */ | ||
| 7053 | { | ||
| 7054 |
1/2✓ Branch 0 taken 15660801 times.
✗ Branch 1 not taken.
|
15660708 | DBUG_TRACE; |
| 7055 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15660801 times.
|
15660801 | assert(hton == innodb_hton_ptr); |
| 7056 | |||
| 7057 |
1/2✓ Branch 0 taken 15660775 times.
✗ Branch 1 not taken.
|
15660801 | trx_t *trx = thd_to_trx(thd); |
| 7058 | 15660775 | bool free_trx = false; | |
| 7059 | |||
| 7060 | /* During server initialization MySQL layer will try to open | ||
| 7061 | some of the master-slave tables those residing in InnoDB. | ||
| 7062 | After MySQL layer is done with needed checks these tables | ||
| 7063 | are closed followed by invocation of close_connection on the | ||
| 7064 | associated thd. | ||
| 7065 | |||
| 7066 | close_connection rolls back the trx and then frees it. | ||
| 7067 | Once trx is freed thd should avoid maintaining reference to | ||
| 7068 | it else it can be classified as stale reference. | ||
| 7069 | |||
| 7070 | Re-invocation of innodb_close_connection on same thd should | ||
| 7071 | get trx as NULL. */ | ||
| 7072 | |||
| 7073 |
2/2✓ Branch 0 taken 15660588 times.
✓ Branch 1 taken 187 times.
|
15660775 | if (trx != nullptr) { |
| 7074 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15660567 times.
|
15660588 | ut_ad(trx->mysql_thd == thd); |
| 7075 |
1/2✓ Branch 0 taken 15660360 times.
✗ Branch 1 not taken.
|
15660567 | TrxInInnoDB trx_in_innodb(trx); |
| 7076 | |||
| 7077 |
2/4✓ Branch 0 taken 15660329 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15660329 times.
|
15660360 | if (trx_in_innodb.is_aborted()) { |
| 7078 | ✗ | while (trx_is_started(trx)) { | |
| 7079 | ✗ | std::this_thread::sleep_for(std::chrono::microseconds(20)); | |
| 7080 | } | ||
| 7081 | } | ||
| 7082 | |||
| 7083 |
5/8✓ Branch 0 taken 15660111 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 15660415 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15660415 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15660438 times.
|
15660329 | if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) { |
| 7084 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE); | |
| 7085 | } | ||
| 7086 | |||
| 7087 | /* Disconnect causes rollback in the following cases: | ||
| 7088 | - trx is not started, or | ||
| 7089 | - trx is in *not* in PREPARED state, or | ||
| 7090 | - trx has not updated any persistent data. | ||
| 7091 | TODO/FIXME: it does not make sense to initiate rollback | ||
| 7092 | in the 1st and 3rd case. */ | ||
| 7093 |
3/4✓ Branch 0 taken 15660407 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 15660405 times.
|
15660438 | if (trx_is_started(trx)) { |
| 7094 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | if (trx_state_eq(trx, TRX_STATE_PREPARED)) { |
| 7095 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (trx_is_redo_rseg_updated(trx)) { |
| 7096 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | trx_disconnect_prepared(trx); |
| 7097 | } else { | ||
| 7098 | ✗ | trx_rollback_for_mysql(trx); | |
| 7099 | ✗ | trx_deregister_from_2pc(trx); | |
| 7100 | ✗ | free_trx = true; | |
| 7101 | } | ||
| 7102 | } else { | ||
| 7103 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_CLOSING_CONNECTION_ROLLS_BACK, | |
| 7104 | trx->undo_no); | ||
| 7105 | ✗ | ut_d(ib::warn(ER_IB_MSG_549) | |
| 7106 | << "trx: " << trx << " started on: " | ||
| 7107 | << innobase_basename(trx->start_file) << ":" << trx->start_line); | ||
| 7108 | ✗ | innobase_rollback_trx(trx); | |
| 7109 | ✗ | free_trx = true; | |
| 7110 | } | ||
| 7111 | } else { | ||
| 7112 |
1/2✓ Branch 0 taken 15660455 times.
✗ Branch 1 not taken.
|
15660405 | innobase_rollback_trx(trx); |
| 7113 | 15660455 | free_trx = true; | |
| 7114 | } | ||
| 7115 | 15660457 | } | |
| 7116 | |||
| 7117 | /* Free trx only after TrxInInnoDB is deleted. */ | ||
| 7118 |
2/2✓ Branch 0 taken 15660532 times.
✓ Branch 1 taken 188 times.
|
15660720 | if (free_trx) { |
| 7119 |
1/2✓ Branch 0 taken 15660620 times.
✗ Branch 1 not taken.
|
15660532 | trx_free_for_mysql(trx); |
| 7120 | } | ||
| 7121 | |||
| 7122 |
1/2✓ Branch 0 taken 15660829 times.
✗ Branch 1 not taken.
|
15660808 | ut::delete_(thd_to_innodb_session(thd)); |
| 7123 | |||
| 7124 |
1/2✓ Branch 0 taken 15660828 times.
✗ Branch 1 not taken.
|
15660828 | thd_to_innodb_session(thd) = nullptr; |
| 7125 | |||
| 7126 | 15660828 | return 0; | |
| 7127 | 15660828 | } | |
| 7128 | |||
| 7129 | /** Cancel any pending lock request associated with the current THD. */ | ||
| 7130 | 1431 | static void innobase_kill_connection( | |
| 7131 | handlerton *hton, /*!< in: innobase handlerton */ | ||
| 7132 | THD *thd) /*!< in: handle to the MySQL thread being | ||
| 7133 | killed */ | ||
| 7134 | { | ||
| 7135 |
1/2✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
|
1431 | DBUG_TRACE; |
| 7136 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1431 times.
|
1431 | assert(hton == innodb_hton_ptr); |
| 7137 | |||
| 7138 |
1/2✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
|
1431 | trx_t *trx = thd_to_trx(thd); |
| 7139 | |||
| 7140 |
1/2✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
|
1431 | if (trx != nullptr) { |
| 7141 | /* Cancel a pending lock request if there are any */ | ||
| 7142 |
2/4✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1431 times.
✗ Branch 3 not taken.
|
1431 | lock_cancel_if_waiting_and_release({trx}); |
| 7143 | } | ||
| 7144 | 1431 | } | |
| 7145 | |||
| 7146 | /** ** InnoDB database tables | ||
| 7147 | *****************************************************************************/ | ||
| 7148 | |||
| 7149 | /** The requested compressed page size (key_block_size) | ||
| 7150 | is given in kilobytes. If it is a valid number, store | ||
| 7151 | that value as the number of log2 shifts from 512 in | ||
| 7152 | zip_ssize. Zero means it is not compressed. */ | ||
| 7153 | 572 | static uint32_t get_zip_shift_size(ulint key_block_size) { | |
| 7154 | uint32_t zssize; /* Zip Shift Size */ | ||
| 7155 | uint32_t kbsize; /* Key Block Size */ | ||
| 7156 | const uint32_t zip_ssize_max = | ||
| 7157 | 1144 | std::min(static_cast<uint32_t>(UNIV_PAGE_SSIZE_MAX), | |
| 7158 | 572 | static_cast<uint32_t>(PAGE_ZIP_SSIZE_MAX)); | |
| 7159 |
2/2✓ Branch 0 taken 1548 times.
✓ Branch 1 taken 10 times.
|
1558 | for (zssize = kbsize = 1; zssize <= zip_ssize_max; zssize++, kbsize <<= 1) { |
| 7160 |
2/2✓ Branch 0 taken 562 times.
✓ Branch 1 taken 986 times.
|
1548 | if (kbsize == key_block_size) { |
| 7161 | 562 | return (zssize); | |
| 7162 | } | ||
| 7163 | } | ||
| 7164 | 10 | return (0); | |
| 7165 | } | ||
| 7166 | |||
| 7167 | /** Get real row type for the table created based on one specified by user, | ||
| 7168 | CREATE TABLE options and SE capabilities. | ||
| 7169 | |||
| 7170 | @note The current code in this method is redundant with/copy of code from | ||
| 7171 | create_table_info_t::innobase_table_flags(). This is temporary workaround. | ||
| 7172 | In future this method will always return ROW_TYPE_DYNAMIC | ||
| 7173 | (which is suitable for intrisinc temporary tables) | ||
| 7174 | and rely on adjusting row format in table definition at ha_innobase::create() | ||
| 7175 | or ha_innobase::prepare_inplace_alter_table() time. | ||
| 7176 | */ | ||
| 7177 | 731284 | enum row_type ha_innobase::get_real_row_type( | |
| 7178 | const HA_CREATE_INFO *create_info) const { | ||
| 7179 | 731284 | const bool is_temp = create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 7180 | 731284 | row_type rt = create_info->row_type; | |
| 7181 | |||
| 7182 |
4/4✓ Branch 0 taken 188490 times.
✓ Branch 1 taken 542794 times.
✓ Branch 2 taken 145947 times.
✓ Branch 3 taken 42543 times.
|
731284 | if (is_temp && (create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE)) { |
| 7183 | 145947 | return (ROW_TYPE_DYNAMIC); | |
| 7184 | } | ||
| 7185 | |||
| 7186 |
2/2✓ Branch 0 taken 163 times.
✓ Branch 1 taken 219045 times.
|
219208 | if (rt == ROW_TYPE_DEFAULT && create_info->key_block_size && |
| 7187 |
10/10✓ Branch 0 taken 219208 times.
✓ Branch 1 taken 366129 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 149 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 139 times.
✓ Branch 8 taken 140 times.
✓ Branch 9 taken 585197 times.
|
804555 | get_zip_shift_size(create_info->key_block_size) && !is_temp && |
| 7188 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
|
10 | (srv_file_per_table || tablespace_is_shared_space(create_info))) { |
| 7189 | 140 | rt = ROW_TYPE_COMPRESSED; | |
| 7190 | } | ||
| 7191 | |||
| 7192 |
4/4✓ Branch 0 taken 365103 times.
✓ Branch 1 taken 1154 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 219069 times.
|
585337 | switch (rt) { |
| 7193 | 365103 | case ROW_TYPE_REDUNDANT: | |
| 7194 | case ROW_TYPE_DYNAMIC: | ||
| 7195 | case ROW_TYPE_COMPACT: | ||
| 7196 | 365103 | return (rt); | |
| 7197 | 1154 | case ROW_TYPE_COMPRESSED: | |
| 7198 |
6/6✓ Branch 0 taken 1128 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1115 times.
✓ Branch 4 taken 1118 times.
✓ Branch 5 taken 36 times.
|
1167 | if (!is_temp && |
| 7199 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
|
13 | (srv_file_per_table || tablespace_is_shared_space(create_info))) { |
| 7200 | 1118 | return (rt); | |
| 7201 | } else { | ||
| 7202 | 36 | return (ROW_TYPE_DYNAMIC); | |
| 7203 | } | ||
| 7204 | 11 | case ROW_TYPE_NOT_USED: | |
| 7205 | case ROW_TYPE_FIXED: | ||
| 7206 | case ROW_TYPE_PAGED: | ||
| 7207 | 11 | return (ROW_TYPE_DYNAMIC); | |
| 7208 | 219069 | case ROW_TYPE_DEFAULT: | |
| 7209 | default: | ||
| 7210 |
4/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 93 times.
✓ Branch 2 taken 218961 times.
✓ Branch 3 taken 2 times.
|
219069 | switch (innodb_default_row_format) { |
| 7211 | 13 | case DEFAULT_ROW_FORMAT_REDUNDANT: | |
| 7212 | 13 | return (ROW_TYPE_REDUNDANT); | |
| 7213 | 93 | case DEFAULT_ROW_FORMAT_COMPACT: | |
| 7214 | 93 | return (ROW_TYPE_COMPACT); | |
| 7215 | 218961 | case DEFAULT_ROW_FORMAT_DYNAMIC: | |
| 7216 | 218961 | return (ROW_TYPE_DYNAMIC); | |
| 7217 | 2 | default: | |
| 7218 | 2 | ut_d(ut_error); | |
| 7219 | ut_o(return (ROW_TYPE_DYNAMIC)); | ||
| 7220 | } | ||
| 7221 | } | ||
| 7222 | } | ||
| 7223 | |||
| 7224 | /** Get the table flags to use for the statement. | ||
| 7225 | @return table flags */ | ||
| 7226 | |||
| 7227 | 250393175 | handler::Table_flags ha_innobase::table_flags() const { | |
| 7228 | 250393175 | THD *thd = ha_thd(); | |
| 7229 | 250395531 | handler::Table_flags flags = m_int_table_flags; | |
| 7230 | |||
| 7231 | /* If querying the table flags when no table_share is given, | ||
| 7232 | then we must check if the table to be created/checked is partitioned. | ||
| 7233 | */ | ||
| 7234 |
6/6✓ Branch 0 taken 2828662 times.
✓ Branch 1 taken 247566869 times.
✓ Branch 2 taken 25881 times.
✓ Branch 3 taken 2802899 times.
✓ Branch 4 taken 25881 times.
✓ Branch 5 taken 250369768 times.
|
250395531 | if (table_share == nullptr && thd_get_work_part_info(thd) != nullptr) { |
| 7235 | /* Currently ha_innopart does not support | ||
| 7236 | all InnoDB features such as GEOMETRY, FULLTEXT etc. */ | ||
| 7237 | 25881 | flags &= ~(HA_INNOPART_DISABLED_TABLE_FLAGS); | |
| 7238 | } | ||
| 7239 | |||
| 7240 | /* Temporary table provides accurate record count */ | ||
| 7241 |
2/2✓ Branch 0 taken 247566888 times.
✓ Branch 1 taken 2828761 times.
|
250395649 | if (table_share != nullptr && |
| 7242 |
2/2✓ Branch 0 taken 677044 times.
✓ Branch 1 taken 246889844 times.
|
247566888 | table_share->table_category == TABLE_CATEGORY_TEMPORARY) { |
| 7243 | 677044 | flags |= HA_STATS_RECORDS_IS_EXACT; | |
| 7244 | } | ||
| 7245 | |||
| 7246 | /* Need to use tx_isolation here since table flags is (also) | ||
| 7247 | called before prebuilt is inited. */ | ||
| 7248 | |||
| 7249 | 250395649 | ulong const tx_isolation = thd_tx_isolation(thd); | |
| 7250 | |||
| 7251 |
2/2✓ Branch 0 taken 156370828 times.
✓ Branch 1 taken 94024502 times.
|
250395330 | if (tx_isolation <= ISO_READ_COMMITTED) { |
| 7252 | 156370828 | return (flags); | |
| 7253 | } | ||
| 7254 | |||
| 7255 | 94024502 | return (flags | HA_BINLOG_STMT_CAPABLE); | |
| 7256 | } | ||
| 7257 | |||
| 7258 | /** Returns the table type (storage engine name). | ||
| 7259 | @return table type */ | ||
| 7260 | |||
| 7261 | 148055 | const char *ha_innobase::table_type() const { return (innobase_hton_name); } | |
| 7262 | |||
| 7263 | /** Returns the operations supported for indexes. | ||
| 7264 | @return flags of supported operations */ | ||
| 7265 | |||
| 7266 | 43268747 | ulong ha_innobase::index_flags(uint key, uint, bool) const { | |
| 7267 |
2/2✓ Branch 0 taken 16802 times.
✓ Branch 1 taken 43251945 times.
|
43268747 | if (table_share->key_info[key].algorithm == HA_KEY_ALG_FULLTEXT) { |
| 7268 | 16802 | return (0); | |
| 7269 | } | ||
| 7270 | |||
| 7271 | 43251945 | ulong flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE | | |
| 7272 | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN; | ||
| 7273 | |||
| 7274 | /* For spatial index, we don't support descending scan | ||
| 7275 | and ICP so far. */ | ||
| 7276 |
2/2✓ Branch 0 taken 9263 times.
✓ Branch 1 taken 43242682 times.
|
43251945 | if (table_share->key_info[key].flags & HA_SPATIAL) { |
| 7277 | 9263 | flags = HA_READ_NEXT | HA_READ_ORDER | HA_READ_RANGE | HA_KEYREAD_ONLY | | |
| 7278 | HA_KEY_SCAN_NOT_ROR; | ||
| 7279 | 9263 | return (flags); | |
| 7280 | } | ||
| 7281 | |||
| 7282 | /* For dd tables mysql.*, we disable ICP for them, | ||
| 7283 | it's for avoiding recusively access same page. */ | ||
| 7284 | /* TODO: Remove these code once the recursiveely access issue which | ||
| 7285 | caused by ICP fixed. */ | ||
| 7286 | 43242682 | const char *dbname = table_share->db.str; | |
| 7287 |
4/4✓ Branch 0 taken 41405159 times.
✓ Branch 1 taken 1837523 times.
✓ Branch 2 taken 28539052 times.
✓ Branch 3 taken 12866107 times.
|
43242682 | if (dbname && strstr(dbname, dict_sys_t::s_dd_space_name) != nullptr && |
| 7288 |
2/2✓ Branch 0 taken 28354042 times.
✓ Branch 1 taken 185010 times.
|
28539052 | strlen(dbname) == 5) { |
| 7289 | 28354042 | flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE | | |
| 7290 | HA_KEYREAD_ONLY; | ||
| 7291 | } | ||
| 7292 | |||
| 7293 | /* Multi-valued keys don't support ordered retrieval, neither they're | ||
| 7294 | suitable for keyread only retrieval. */ | ||
| 7295 |
2/2✓ Branch 0 taken 6358 times.
✓ Branch 1 taken 43236324 times.
|
43242682 | if (table_share->key_info[key].flags & HA_MULTI_VALUED_KEY) { |
| 7296 | 6358 | flags &= ~(HA_READ_ORDER | HA_KEYREAD_ONLY); | |
| 7297 | } | ||
| 7298 | |||
| 7299 | 43242682 | return (flags); | |
| 7300 | } | ||
| 7301 | |||
| 7302 | /** Returns the maximum number of keys. | ||
| 7303 | @return MAX_KEY */ | ||
| 7304 | |||
| 7305 | 586811 | uint ha_innobase::max_supported_keys() const { return (MAX_KEY); } | |
| 7306 | |||
| 7307 | /** Returns the maximum key length. | ||
| 7308 | @return maximum supported key length, in bytes */ | ||
| 7309 | |||
| 7310 | 1221866 | uint ha_innobase::max_supported_key_length() const { | |
| 7311 | /* An InnoDB page must store >= 2 keys; a secondary key record | ||
| 7312 | must also contain the primary key value. Therefore, if both | ||
| 7313 | the primary key and the secondary key are at this maximum length, | ||
| 7314 | it must be less than 1/4th of the free space on a page including | ||
| 7315 | record overhead. | ||
| 7316 | |||
| 7317 | MySQL imposes its own limit to this number; MAX_KEY_LENGTH = 3072. | ||
| 7318 | |||
| 7319 | For page sizes = 16k, InnoDB historically reported 3500 bytes here, | ||
| 7320 | But the MySQL limit of 3072 was always used through the handler | ||
| 7321 | interface. */ | ||
| 7322 | |||
| 7323 |
1/3✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1221866 times.
|
1221866 | switch (UNIV_PAGE_SIZE) { |
| 7324 | ✗ | case 4096: | |
| 7325 | ✗ | return (768); | |
| 7326 | ✗ | case 8192: | |
| 7327 | ✗ | return (1536); | |
| 7328 | 1221866 | default: | |
| 7329 | 1221866 | return (3500); | |
| 7330 | } | ||
| 7331 | } | ||
| 7332 | |||
| 7333 | /** Determines if the primary key is clustered index. | ||
| 7334 | @return true */ | ||
| 7335 | |||
| 7336 | 12037882 | bool ha_innobase::primary_key_is_clustered() const { return (true); } | |
| 7337 | |||
| 7338 | 5969570 | bool create_table_info_t::normalize_table_name(char *norm_name, | |
| 7339 | const char *name) { | ||
| 7340 | const char *name_ptr; | ||
| 7341 | ulint name_len; | ||
| 7342 | const char *db_ptr; | ||
| 7343 | ulint db_len; | ||
| 7344 | const char *ptr; | ||
| 7345 | ulint norm_len; | ||
| 7346 | |||
| 7347 | /* Scan name from the end */ | ||
| 7348 | |||
| 7349 | 5969570 | ptr = strend(name) - 1; | |
| 7350 | |||
| 7351 | /* seek to the last path separator */ | ||
| 7352 |
6/6✓ Branch 0 taken 79373321 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 79373299 times.
✓ Branch 3 taken 22 times.
✓ Branch 4 taken 73403734 times.
✓ Branch 5 taken 5969565 times.
|
79373323 | while (ptr >= name && *ptr != '\\' && *ptr != '/') { |
| 7353 | 73403734 | ptr--; | |
| 7354 | } | ||
| 7355 | |||
| 7356 | 5969589 | name_ptr = ptr + 1; | |
| 7357 | 5969589 | name_len = strlen(name_ptr); | |
| 7358 | |||
| 7359 | /* skip any number of path separators */ | ||
| 7360 |
5/6✓ Branch 0 taken 11939179 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11939183 times.
✓ Branch 4 taken 5969597 times.
✓ Branch 5 taken 5969586 times.
|
11939182 | while (ptr >= name && (*ptr == '\\' || *ptr == '/')) { |
| 7361 | 5969593 | ptr--; | |
| 7362 | } | ||
| 7363 | |||
| 7364 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5969589 times.
|
5969589 | assert(ptr >= name); |
| 7365 | |||
| 7366 | /* seek to the last but one path separator or one char before | ||
| 7367 | the beginning of name */ | ||
| 7368 | 5969589 | db_len = 0; | |
| 7369 |
6/6✓ Branch 0 taken 37083009 times.
✓ Branch 1 taken 114630 times.
✓ Branch 2 taken 37082998 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 31228050 times.
✓ Branch 5 taken 5854948 times.
|
37197639 | while (ptr >= name && *ptr != '\\' && *ptr != '/') { |
| 7370 | 31228050 | ptr--; | |
| 7371 | 31228050 | db_len++; | |
| 7372 | } | ||
| 7373 | |||
| 7374 | 5969589 | db_ptr = ptr + 1; | |
| 7375 | |||
| 7376 | 5969589 | norm_len = db_len + name_len + sizeof "/"; | |
| 7377 | |||
| 7378 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5969589 times.
|
5969589 | if (norm_len >= FN_REFLEN - 1) { |
| 7379 | /* purecov: begin assert */ | ||
| 7380 | ✗ | ut_d(ut_error); | |
| 7381 | ut_o(return (false)); | ||
| 7382 | /* purecov: end */ | ||
| 7383 | } | ||
| 7384 | |||
| 7385 | 5969589 | memcpy(norm_name, db_ptr, db_len); | |
| 7386 | |||
| 7387 | 5969589 | norm_name[db_len] = '/'; | |
| 7388 | |||
| 7389 | /* Copy the name and null-byte. */ | ||
| 7390 | 5969589 | memcpy(norm_name + db_len + 1, name_ptr, name_len + 1); | |
| 7391 | |||
| 7392 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5969589 times.
|
5969589 | if (lower_case_file_system) { |
| 7393 | ✗ | ut_ad(lower_case_table_names != 0); | |
| 7394 | ✗ | innobase_casedn_str(norm_name); | |
| 7395 | } | ||
| 7396 | 5969577 | return (true); | |
| 7397 | } | ||
| 7398 | |||
| 7399 | #ifdef UNIV_DEBUG | ||
| 7400 | /********************************************************************* | ||
| 7401 | Test normalize_table_name(). */ | ||
| 7402 | ✗ | static void test_normalize_table_name() { | |
| 7403 | char norm_name[FN_REFLEN]; | ||
| 7404 | ✗ | const char *test_data[][2] = { | |
| 7405 | /* input, expected result */ | ||
| 7406 | {"./mysqltest/t1", "mysqltest/t1"}, | ||
| 7407 | {"./test/#sql-842b_2", "test/#sql-842b_2"}, | ||
| 7408 | {"./test/#sql-85a3_10", "test/#sql-85a3_10"}, | ||
| 7409 | {"./test/#sql2-842b-2", "test/#sql2-842b-2"}, | ||
| 7410 | {"./test/bug29807", "test/bug29807"}, | ||
| 7411 | {"./test/foo", "test/foo"}, | ||
| 7412 | {"./test/innodb_bug52663", "test/innodb_bug52663"}, | ||
| 7413 | {"./test/t", "test/t"}, | ||
| 7414 | {"./test/t1", "test/t1"}, | ||
| 7415 | {"./test/t10", "test/t10"}, | ||
| 7416 | {"/a/b/db/table", "db/table"}, | ||
| 7417 | {"/a/b/db///////table", "db/table"}, | ||
| 7418 | {"/a/b////db///////table", "db/table"}, | ||
| 7419 | {"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"}, | ||
| 7420 | {"db/table", "db/table"}, | ||
| 7421 | {"ddd/t", "ddd/t"}, | ||
| 7422 | {"d/ttt", "d/ttt"}, | ||
| 7423 | {"d/t", "d/t"}, | ||
| 7424 | {".\\mysqltest\\t1", "mysqltest/t1"}, | ||
| 7425 | {".\\test\\#sql-842b_2", "test/#sql-842b_2"}, | ||
| 7426 | {".\\test\\#sql-85a3_10", "test/#sql-85a3_10"}, | ||
| 7427 | {".\\test\\#sql2-842b-2", "test/#sql2-842b-2"}, | ||
| 7428 | {".\\test\\bug29807", "test/bug29807"}, | ||
| 7429 | {".\\test\\foo", "test/foo"}, | ||
| 7430 | {".\\test\\innodb_bug52663", "test/innodb_bug52663"}, | ||
| 7431 | {".\\test\\t", "test/t"}, | ||
| 7432 | {".\\test\\t1", "test/t1"}, | ||
| 7433 | {".\\test\\t10", "test/t10"}, | ||
| 7434 | {"C:\\a\\b\\db\\table", "db/table"}, | ||
| 7435 | {"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"}, | ||
| 7436 | {"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"}, | ||
| 7437 | {"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"}, | ||
| 7438 | {"db\\table", "db/table"}, | ||
| 7439 | {"ddd\\t", "ddd/t"}, | ||
| 7440 | {"d\\ttt", "d/ttt"}, | ||
| 7441 | {"d\\t", "d/t"}, | ||
| 7442 | }; | ||
| 7443 | |||
| 7444 | ✗ | for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) { | |
| 7445 | ✗ | printf( | |
| 7446 | "test_normalize_table_name():" | ||
| 7447 | " testing \"%s\", expected \"%s\"... ", | ||
| 7448 | test_data[i][0], test_data[i][1]); | ||
| 7449 | |||
| 7450 | ✗ | create_table_info_t::normalize_table_name(norm_name, test_data[i][0]); | |
| 7451 | |||
| 7452 | ✗ | if (strcmp(norm_name, test_data[i][1]) == 0) { | |
| 7453 | ✗ | printf("ok\n"); | |
| 7454 | } else { | ||
| 7455 | ✗ | printf("got \"%s\"\n", norm_name); | |
| 7456 | ✗ | ut_error; | |
| 7457 | } | ||
| 7458 | } | ||
| 7459 | } | ||
| 7460 | |||
| 7461 | /********************************************************************* | ||
| 7462 | Test ut_format_name(). */ | ||
| 7463 | 1 | static void test_ut_format_name() { | |
| 7464 | char buf[NAME_LEN * 3]; | ||
| 7465 | |||
| 7466 | struct { | ||
| 7467 | const char *name; | ||
| 7468 | ulint buf_size; | ||
| 7469 | const char *expected; | ||
| 7470 | 1 | } test_data[] = { | |
| 7471 | {"test/t1", sizeof(buf), "`test`.`t1`"}, | ||
| 7472 | {"test/t1", 12, "`test`.`t1`"}, | ||
| 7473 | {"test/t1", 11, "`test`.`t1"}, | ||
| 7474 | {"test/t1", 10, "`test`.`t"}, | ||
| 7475 | {"test/t1", 9, "`test`.`"}, | ||
| 7476 | {"test/t1", 8, "`test`."}, | ||
| 7477 | {"test/t1", 7, "`test`"}, | ||
| 7478 | {"test/t1", 6, "`test"}, | ||
| 7479 | {"test/t1", 5, "`tes"}, | ||
| 7480 | {"test/t1", 4, "`te"}, | ||
| 7481 | {"test/t1", 3, "`t"}, | ||
| 7482 | {"test/t1", 2, "`"}, | ||
| 7483 | {"test/t1", 1, ""}, | ||
| 7484 | {"test/t1", 0, "BUF_NOT_CHANGED"}, | ||
| 7485 | {"table", sizeof(buf), "`table`"}, | ||
| 7486 | {"ta'le", sizeof(buf), "`ta'le`"}, | ||
| 7487 | {"ta\"le", sizeof(buf), "`ta\"le`"}, | ||
| 7488 | {"ta`le", sizeof(buf), "`ta``le`"}, | ||
| 7489 | }; | ||
| 7490 | |||
| 7491 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1 times.
|
19 | for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) { |
| 7492 | 18 | memcpy(buf, "BUF_NOT_CHANGED", strlen("BUF_NOT_CHANGED") + 1); | |
| 7493 | |||
| 7494 | char *ret; | ||
| 7495 | |||
| 7496 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | ret = ut_format_name(test_data[i].name, buf, test_data[i].buf_size); |
| 7497 | |||
| 7498 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | ut_a(ret == buf); |
| 7499 | |||
| 7500 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (strcmp(buf, test_data[i].expected) == 0) { |
| 7501 |
3/6✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
36 | ib::info(ER_IB_MSG_550) << "ut_format_name(" << test_data[i].name |
| 7502 |
2/4✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | << ", buf, " << test_data[i].buf_size |
| 7503 | << ")," | ||
| 7504 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | " expected " |
| 7505 |
2/4✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | << test_data[i].expected << ", OK"; |
| 7506 | } else { | ||
| 7507 | ✗ | ib::error(ER_IB_MSG_551) | |
| 7508 | ✗ | << "ut_format_name(" << test_data[i].name << ", buf, " | |
| 7509 | ✗ | << test_data[i].buf_size | |
| 7510 | << ")," | ||
| 7511 | ✗ | " expected " | |
| 7512 | ✗ | << test_data[i].expected << ", ERROR: got " << buf; | |
| 7513 | ✗ | ut_error; | |
| 7514 | } | ||
| 7515 | } | ||
| 7516 | 1 | } | |
| 7517 | #endif /* UNIV_DEBUG */ | ||
| 7518 | |||
| 7519 | /** Match index columns between MySQL and InnoDB. | ||
| 7520 | This function checks whether the index column information | ||
| 7521 | is consistent between KEY info from mysql and that from innodb index. | ||
| 7522 | @param[in] key_info Index info from mysql | ||
| 7523 | @param[in] index_info Index info from InnoDB | ||
| 7524 | @return true if all column types match. */ | ||
| 7525 | 4055820 | bool innobase_match_index_columns(const KEY *key_info, | |
| 7526 | const dict_index_t *index_info) { | ||
| 7527 | const KEY_PART_INFO *key_part; | ||
| 7528 | const KEY_PART_INFO *key_end; | ||
| 7529 | const dict_field_t *innodb_idx_fld; | ||
| 7530 | const dict_field_t *innodb_idx_fld_end; | ||
| 7531 | |||
| 7532 |
1/2✓ Branch 0 taken 4055820 times.
✗ Branch 1 not taken.
|
4055820 | DBUG_TRACE; |
| 7533 | |||
| 7534 | /* Check whether user defined index column count matches */ | ||
| 7535 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4055820 times.
|
4055820 | if (key_info->user_defined_key_parts != index_info->n_user_defined_cols) { |
| 7536 | ✗ | return false; | |
| 7537 | } | ||
| 7538 | |||
| 7539 | 4055820 | key_part = key_info->key_part; | |
| 7540 | 4055820 | key_end = key_part + key_info->user_defined_key_parts; | |
| 7541 | 4055820 | innodb_idx_fld = index_info->fields; | |
| 7542 | 4055820 | innodb_idx_fld_end = index_info->fields + index_info->n_fields; | |
| 7543 | |||
| 7544 | /* Check each index column's datatype. We do not check | ||
| 7545 | column name because there exists case that index | ||
| 7546 | column name got modified in mysql but such change does not | ||
| 7547 | propagate to InnoDB. | ||
| 7548 | One hidden assumption here is that the index column sequences | ||
| 7549 | are matched up between those in mysql and InnoDB. */ | ||
| 7550 |
2/2✓ Branch 0 taken 6851620 times.
✓ Branch 1 taken 4055820 times.
|
10907440 | for (; key_part != key_end; ++key_part) { |
| 7551 | ulint col_type; | ||
| 7552 | ulint is_unsigned; | ||
| 7553 | 6851620 | ulint mtype = innodb_idx_fld->col->mtype; | |
| 7554 | |||
| 7555 | /* Need to translate to InnoDB column type before | ||
| 7556 | comparison. */ | ||
| 7557 |
1/2✓ Branch 0 taken 6851620 times.
✗ Branch 1 not taken.
|
6851620 | col_type = get_innobase_type_from_mysql_type(&is_unsigned, key_part->field); |
| 7558 | |||
| 7559 | /* Ignore InnoDB specific system columns. */ | ||
| 7560 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6851620 times.
|
6851620 | while (mtype == DATA_SYS) { |
| 7561 | ✗ | innodb_idx_fld++; | |
| 7562 | |||
| 7563 | ✗ | if (innodb_idx_fld >= innodb_idx_fld_end) { | |
| 7564 | ✗ | return false; | |
| 7565 | } | ||
| 7566 | } | ||
| 7567 | |||
| 7568 | 6851620 | if ((bool)innodb_idx_fld->is_ascending != | |
| 7569 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6851620 times.
|
6851620 | !(key_part->key_part_flag & HA_REVERSE_SORT)) { |
| 7570 | /* Column Type mismatches */ | ||
| 7571 | ✗ | return false; | |
| 7572 | } | ||
| 7573 | |||
| 7574 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6851620 times.
|
6851620 | if (col_type != mtype) { |
| 7575 | /* If the col_type we get from mysql type is a geometry | ||
| 7576 | data type, we should check if mtype is a legacy type | ||
| 7577 | from 5.6, either upgraded to DATA_GEOMETRY or not. | ||
| 7578 | This is indeed not an accurate check, but should be | ||
| 7579 | safe, since DATA_BLOB would be upgraded once we create | ||
| 7580 | spatial index on it and we intend to use DATA_GEOMETRY | ||
| 7581 | for legacy GIS data types which are of var-length. */ | ||
| 7582 | ✗ | switch (col_type) { | |
| 7583 | ✗ | case DATA_POINT: | |
| 7584 | case DATA_VAR_POINT: | ||
| 7585 | ✗ | if (DATA_POINT_MTYPE(mtype) || mtype == DATA_GEOMETRY || | |
| 7586 | mtype == DATA_BLOB) { | ||
| 7587 | ✗ | break; | |
| 7588 | } | ||
| 7589 | [[fallthrough]]; | ||
| 7590 | case DATA_GEOMETRY: | ||
| 7591 | ✗ | if (mtype == DATA_BLOB) { | |
| 7592 | ✗ | break; | |
| 7593 | } | ||
| 7594 | [[fallthrough]]; | ||
| 7595 | default: | ||
| 7596 | /* Column type mismatches */ | ||
| 7597 | ✗ | return false; | |
| 7598 | } | ||
| 7599 | } | ||
| 7600 | |||
| 7601 | 6851620 | innodb_idx_fld++; | |
| 7602 | } | ||
| 7603 | |||
| 7604 | 4055820 | return true; | |
| 7605 | 4055820 | } | |
| 7606 | |||
| 7607 | /** Build a template for a base column for a virtual column | ||
| 7608 | @param[in] table MySQL TABLE | ||
| 7609 | @param[in] clust_index InnoDB clustered index | ||
| 7610 | @param[in] field field in MySQL table | ||
| 7611 | @param[in] col InnoDB column | ||
| 7612 | @param[in,out] templ template to fill | ||
| 7613 | @param[in] col_no field index for virtual col | ||
| 7614 | */ | ||
| 7615 | 97320 | static void innobase_vcol_build_templ(const TABLE *table, | |
| 7616 | const dict_index_t *clust_index, | ||
| 7617 | Field *field, const dict_col_t *col, | ||
| 7618 | mysql_row_templ_t *templ, ulint col_no) { | ||
| 7619 |
2/2✓ Branch 0 taken 52357 times.
✓ Branch 1 taken 44963 times.
|
97320 | if (col->is_virtual()) { |
| 7620 | 52357 | templ->is_virtual = true; | |
| 7621 | 52357 | templ->col_no = col_no; | |
| 7622 | 52357 | templ->clust_rec_field_no = ULINT_UNDEFINED; | |
| 7623 | 52357 | templ->rec_field_no = col->ind; | |
| 7624 | } else { | ||
| 7625 | 44963 | templ->is_virtual = false; | |
| 7626 | 44963 | templ->col_no = col_no; | |
| 7627 | 44963 | templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index); | |
| 7628 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44963 times.
|
44963 | ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED); |
| 7629 | |||
| 7630 | 44963 | templ->rec_field_no = templ->clust_rec_field_no; | |
| 7631 | } | ||
| 7632 | |||
| 7633 | 97320 | templ->icp_rec_field_no = ULINT_UNDEFINED; | |
| 7634 | |||
| 7635 |
2/2✓ Branch 0 taken 52225 times.
✓ Branch 1 taken 45095 times.
|
97320 | if (field->is_nullable()) { |
| 7636 | 52225 | templ->mysql_null_byte_offset = field->null_offset(); | |
| 7637 | |||
| 7638 | 52225 | templ->mysql_null_bit_mask = (ulint)field->null_bit; | |
| 7639 | } else { | ||
| 7640 | 45095 | templ->mysql_null_bit_mask = 0; | |
| 7641 | } | ||
| 7642 | |||
| 7643 | 97320 | templ->mysql_col_offset = static_cast<ulint>(get_field_offset(table, field)); | |
| 7644 | 97320 | templ->mysql_col_len = static_cast<ulint>(field->pack_length()); | |
| 7645 | /* The multi-value index indexes attribute values in a JSON doc, so its | ||
| 7646 | index field length could be different from the actual column data length */ | ||
| 7647 |
6/6✓ Branch 0 taken 52357 times.
✓ Branch 1 taken 44963 times.
✓ Branch 2 taken 582 times.
✓ Branch 3 taken 51775 times.
✓ Branch 4 taken 582 times.
✓ Branch 5 taken 96738 times.
|
97320 | if (templ->is_virtual && innobase_is_multi_value_fld(field)) { |
| 7648 | 582 | templ->mysql_mvidx_len = static_cast<ulint>(field->key_length()); | |
| 7649 | 582 | templ->is_multi_val = true; | |
| 7650 | } else { | ||
| 7651 | 96738 | templ->mysql_mvidx_len = 0; | |
| 7652 | 96738 | templ->is_multi_val = false; | |
| 7653 | } | ||
| 7654 | |||
| 7655 | 97320 | templ->type = col->mtype; | |
| 7656 | 97320 | templ->mysql_type = static_cast<ulint>(field->type()); | |
| 7657 | |||
| 7658 |
2/2✓ Branch 0 taken 41596 times.
✓ Branch 1 taken 55724 times.
|
97320 | if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { |
| 7659 | 41596 | templ->mysql_length_bytes = field->get_length_bytes(); | |
| 7660 | } | ||
| 7661 | |||
| 7662 | 97320 | templ->charset = dtype_get_charset_coll(col->prtype); | |
| 7663 | 97320 | templ->mbminlen = col->get_mbminlen(); | |
| 7664 | 97320 | templ->mbmaxlen = col->get_mbmaxlen(); | |
| 7665 | 97320 | templ->is_unsigned = col->prtype & DATA_UNSIGNED; | |
| 7666 | 97320 | templ->compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED); | |
| 7667 | 97320 | templ->zip_dict_data = field->zip_dict_data; | |
| 7668 | 97320 | } | |
| 7669 | |||
| 7670 | /** Callback used by MySQL server layer to initialize | ||
| 7671 | the table virtual columns' template | ||
| 7672 | @param[in] table MySQL TABLE | ||
| 7673 | @param[in,out] ib_table InnoDB table */ | ||
| 7674 | 2 | void innobase_build_v_templ_callback(const TABLE *table, void *ib_table) { | |
| 7675 | 2 | const dict_table_t *t_table = static_cast<dict_table_t *>(ib_table); | |
| 7676 | |||
| 7677 | 2 | innobase_build_v_templ(table, t_table, t_table->vc_templ, nullptr, true, | |
| 7678 | nullptr); | ||
| 7679 | 2 | } | |
| 7680 | |||
| 7681 | /** Build template for the virtual columns and their base columns. This | ||
| 7682 | is done when the table first opened. | ||
| 7683 | @param[in] table MySQL TABLE | ||
| 7684 | @param[in] ib_table InnoDB dict_table_t | ||
| 7685 | @param[in,out] s_templ InnoDB template structure | ||
| 7686 | @param[in] add_v new virtual columns added along with | ||
| 7687 | add index call | ||
| 7688 | @param[in] locked true if dict_sys mutex is held | ||
| 7689 | @param[in] share_tbl_name original MySQL table name */ | ||
| 7690 | 44950 | void innobase_build_v_templ(const TABLE *table, const dict_table_t *ib_table, | |
| 7691 | dict_vcol_templ_t *s_templ, | ||
| 7692 | const dict_add_v_col_t *add_v, bool locked, | ||
| 7693 | const char *share_tbl_name) { | ||
| 7694 | 44950 | ulint ncol = ib_table->n_cols - DATA_N_SYS_COLS; | |
| 7695 | 44950 | ulint n_v_col = ib_table->n_v_cols; | |
| 7696 | bool marker[REC_MAX_N_FIELDS]; | ||
| 7697 | |||
| 7698 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44950 times.
|
44950 | ut_ad(ncol < REC_MAX_N_FIELDS); |
| 7699 | |||
| 7700 |
2/2✓ Branch 0 taken 166 times.
✓ Branch 1 taken 44784 times.
|
44950 | if (add_v != nullptr) { |
| 7701 | 166 | n_v_col += add_v->n_v_col; | |
| 7702 | } | ||
| 7703 | |||
| 7704 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44950 times.
|
44950 | ut_ad(n_v_col > 0); |
| 7705 | |||
| 7706 |
2/2✓ Branch 0 taken 1066 times.
✓ Branch 1 taken 43884 times.
|
44950 | if (!locked) { |
| 7707 |
1/2✓ Branch 0 taken 1066 times.
✗ Branch 1 not taken.
|
1066 | dict_sys_mutex_enter(); |
| 7708 | } | ||
| 7709 | |||
| 7710 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44950 times.
|
44950 | if (s_templ->vtempl) { |
| 7711 | ✗ | if (!locked) { | |
| 7712 | ✗ | dict_sys_mutex_exit(); | |
| 7713 | } | ||
| 7714 | ✗ | return; | |
| 7715 | } | ||
| 7716 | |||
| 7717 | 44950 | memset(marker, 0, sizeof(bool) * ncol); | |
| 7718 | |||
| 7719 | 44950 | s_templ->vtempl = static_cast<mysql_row_templ_t **>(ut::zalloc_withkey( | |
| 7720 | 44950 | UT_NEW_THIS_FILE_PSI_KEY, (ncol + n_v_col) * sizeof *s_templ->vtempl)); | |
| 7721 | 44950 | s_templ->n_col = ncol; | |
| 7722 | 44950 | s_templ->n_v_col = n_v_col; | |
| 7723 | 44950 | s_templ->rec_len = table->s->reclength; | |
| 7724 | 44950 | s_templ->default_rec = static_cast<byte *>( | |
| 7725 | 44950 | ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY, table->s->reclength)); | |
| 7726 | 44950 | memcpy(s_templ->default_rec, table->s->default_values, table->s->reclength); | |
| 7727 | |||
| 7728 | /* Mark those columns could be base columns */ | ||
| 7729 |
2/2✓ Branch 0 taken 52178 times.
✓ Branch 1 taken 44950 times.
|
97128 | for (ulint i = 0; i < ib_table->n_v_cols; i++) { |
| 7730 |
1/2✓ Branch 0 taken 52178 times.
✗ Branch 1 not taken.
|
52178 | const dict_v_col_t *vcol = dict_table_get_nth_v_col(ib_table, i); |
| 7731 | |||
| 7732 |
2/2✓ Branch 0 taken 51169 times.
✓ Branch 1 taken 52178 times.
|
103347 | for (ulint j = 0; j < vcol->num_base; j++) { |
| 7733 | 51169 | ulint col_no = vcol->base_col[j]->ind; | |
| 7734 | 51169 | marker[col_no] = true; | |
| 7735 | } | ||
| 7736 | } | ||
| 7737 | |||
| 7738 |
2/2✓ Branch 0 taken 166 times.
✓ Branch 1 taken 44784 times.
|
44950 | if (add_v) { |
| 7739 |
2/2✓ Branch 0 taken 179 times.
✓ Branch 1 taken 166 times.
|
345 | for (ulint i = 0; i < add_v->n_v_col; i++) { |
| 7740 | 179 | const dict_v_col_t *vcol = &add_v->v_col[i]; | |
| 7741 | |||
| 7742 |
2/2✓ Branch 0 taken 216 times.
✓ Branch 1 taken 179 times.
|
395 | for (ulint j = 0; j < vcol->num_base; j++) { |
| 7743 | 216 | ulint col_no = vcol->base_col[j]->ind; | |
| 7744 | 216 | marker[col_no] = true; | |
| 7745 | } | ||
| 7746 | } | ||
| 7747 | } | ||
| 7748 | |||
| 7749 | 44950 | ulint j = 0; | |
| 7750 | 44950 | ulint z = 0; | |
| 7751 | |||
| 7752 |
1/2✓ Branch 0 taken 44950 times.
✗ Branch 1 not taken.
|
44950 | const dict_index_t *clust_index = ib_table->first_index(); |
| 7753 | |||
| 7754 |
2/2✓ Branch 0 taken 267237 times.
✓ Branch 1 taken 44950 times.
|
312187 | for (ulint i = 0; i < table->s->fields; i++) { |
| 7755 | 267237 | Field *field = table->field[i]; | |
| 7756 | |||
| 7757 | /* Build template for virtual columns */ | ||
| 7758 |
4/4✓ Branch 0 taken 54683 times.
✓ Branch 1 taken 212554 times.
✓ Branch 2 taken 52357 times.
✓ Branch 3 taken 2326 times.
|
267237 | if (innobase_is_v_fld(field)) { |
| 7759 | #ifdef UNIV_DEBUG | ||
| 7760 | const char *name; | ||
| 7761 | |||
| 7762 |
2/2✓ Branch 0 taken 179 times.
✓ Branch 1 taken 52178 times.
|
52357 | if (z >= ib_table->n_v_def) { |
| 7763 | 179 | name = add_v->v_col_name[z - ib_table->n_v_def]; | |
| 7764 | } else { | ||
| 7765 |
1/2✓ Branch 0 taken 52178 times.
✗ Branch 1 not taken.
|
52178 | name = dict_table_get_v_col_name(ib_table, z); |
| 7766 | } | ||
| 7767 | |||
| 7768 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52357 times.
|
52357 | ut_ad(!ut_strcmp(name, field->field_name)); |
| 7769 | #endif | ||
| 7770 | const dict_v_col_t *vcol; | ||
| 7771 | |||
| 7772 |
2/2✓ Branch 0 taken 179 times.
✓ Branch 1 taken 52178 times.
|
52357 | if (z >= ib_table->n_v_def) { |
| 7773 | 179 | vcol = &add_v->v_col[z - ib_table->n_v_def]; | |
| 7774 | } else { | ||
| 7775 |
1/2✓ Branch 0 taken 52178 times.
✗ Branch 1 not taken.
|
52178 | vcol = dict_table_get_nth_v_col(ib_table, z); |
| 7776 | } | ||
| 7777 | |||
| 7778 | 104714 | s_templ->vtempl[z + s_templ->n_col] = | |
| 7779 | 52357 | static_cast<mysql_row_templ_t *>(ut::malloc_withkey( | |
| 7780 | 52357 | UT_NEW_THIS_FILE_PSI_KEY, sizeof *s_templ->vtempl[j])); | |
| 7781 | |||
| 7782 | 52357 | innobase_vcol_build_templ(table, clust_index, field, &vcol->m_col, | |
| 7783 |
1/2✓ Branch 0 taken 52357 times.
✗ Branch 1 not taken.
|
52357 | s_templ->vtempl[z + s_templ->n_col], z); |
| 7784 | 52357 | z++; | |
| 7785 | 52357 | continue; | |
| 7786 | 52357 | } | |
| 7787 | |||
| 7788 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 214880 times.
|
214880 | ut_ad(j < ncol); |
| 7789 | |||
| 7790 | /* Build template for base columns */ | ||
| 7791 |
2/2✓ Branch 0 taken 44963 times.
✓ Branch 1 taken 169917 times.
|
214880 | if (marker[j]) { |
| 7792 |
1/2✓ Branch 0 taken 44963 times.
✗ Branch 1 not taken.
|
44963 | dict_col_t *col = ib_table->get_col(j); |
| 7793 | |||
| 7794 | #ifdef UNIV_DEBUG | ||
| 7795 |
1/2✓ Branch 0 taken 44963 times.
✗ Branch 1 not taken.
|
44963 | const char *name = ib_table->get_col_name(j); |
| 7796 | |||
| 7797 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44963 times.
|
44963 | ut_ad(!ut_strcmp(name, field->field_name)); |
| 7798 | #endif | ||
| 7799 | |||
| 7800 | 44963 | s_templ->vtempl[j] = static_cast<mysql_row_templ_t *>(ut::malloc_withkey( | |
| 7801 | 44963 | UT_NEW_THIS_FILE_PSI_KEY, sizeof *s_templ->vtempl[j])); | |
| 7802 | |||
| 7803 | 44963 | innobase_vcol_build_templ(table, clust_index, field, col, | |
| 7804 |
1/2✓ Branch 0 taken 44963 times.
✗ Branch 1 not taken.
|
44963 | s_templ->vtempl[j], j); |
| 7805 | } | ||
| 7806 | |||
| 7807 | 214880 | j++; | |
| 7808 | } | ||
| 7809 | |||
| 7810 |
2/2✓ Branch 0 taken 1066 times.
✓ Branch 1 taken 43884 times.
|
44950 | if (!locked) { |
| 7811 |
1/2✓ Branch 0 taken 1066 times.
✗ Branch 1 not taken.
|
1066 | dict_sys_mutex_exit(); |
| 7812 | } | ||
| 7813 | |||
| 7814 |
1/2✓ Branch 0 taken 44950 times.
✗ Branch 1 not taken.
|
44950 | s_templ->db_name = table->s->db.str; |
| 7815 |
1/2✓ Branch 0 taken 44950 times.
✗ Branch 1 not taken.
|
44950 | s_templ->tb_name = table->s->table_name.str; |
| 7816 | |||
| 7817 |
2/2✓ Branch 0 taken 42985 times.
✓ Branch 1 taken 1965 times.
|
44950 | if (share_tbl_name) { |
| 7818 |
1/2✓ Branch 0 taken 42985 times.
✗ Branch 1 not taken.
|
42985 | s_templ->share_name = share_tbl_name; |
| 7819 | } | ||
| 7820 | } | ||
| 7821 | |||
| 7822 | /** This function builds a translation table in INNOBASE_SHARE | ||
| 7823 | structure for fast index location with mysql array number from its | ||
| 7824 | table->key_info structure. This also provides the necessary translation | ||
| 7825 | between the key order in mysql key_info and InnoDB ib_table->indexes if | ||
| 7826 | they are not fully matched with each other. | ||
| 7827 | Note we do not have any mutex protecting the translation table | ||
| 7828 | building based on the assumption that there is no concurrent | ||
| 7829 | index creation/drop and DMLs that requires index lookup. All table | ||
| 7830 | handle will be closed before the index creation/drop. | ||
| 7831 | @return true if index translation table built successfully */ | ||
| 7832 | 4025299 | bool innobase_build_index_translation( | |
| 7833 | const TABLE *table, /*!< in: table in MySQL data | ||
| 7834 | dictionary */ | ||
| 7835 | dict_table_t *ib_table, /*!< in: table in InnoDB data | ||
| 7836 | dictionary */ | ||
| 7837 | INNOBASE_SHARE *share) /*!< in/out: share structure | ||
| 7838 | where index translation table | ||
| 7839 | will be constructed in. */ | ||
| 7840 | { | ||
| 7841 |
1/2✓ Branch 0 taken 4025302 times.
✗ Branch 1 not taken.
|
4025299 | DBUG_TRACE; |
| 7842 | |||
| 7843 | 4025302 | bool ret = true; | |
| 7844 | |||
| 7845 |
1/2✓ Branch 0 taken 4025302 times.
✗ Branch 1 not taken.
|
4025302 | dict_sys_mutex_enter(); |
| 7846 | |||
| 7847 | 4025302 | ulint mysql_num_index = table->s->keys; | |
| 7848 |
1/2✓ Branch 0 taken 4025302 times.
✗ Branch 1 not taken.
|
4025302 | ulint ib_num_index = UT_LIST_GET_LEN(ib_table->indexes); |
| 7849 | 4025302 | dict_index_t **index_mapping = share->idx_trans_tbl.index_mapping; | |
| 7850 | |||
| 7851 | /* If there exists inconsistency between MySQL and InnoDB dictionary | ||
| 7852 | (metadata) information, the number of index defined in MySQL | ||
| 7853 | could exceed that in InnoDB, do not build index translation | ||
| 7854 | table in such case */ | ||
| 7855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4025302 times.
|
4025302 | if (ib_num_index < mysql_num_index) { |
| 7856 | ✗ | ret = false; | |
| 7857 | ✗ | goto func_exit; | |
| 7858 | } | ||
| 7859 | |||
| 7860 | /* If index entry count is non-zero, nothing has | ||
| 7861 | changed since last update, directly return true */ | ||
| 7862 |
2/2✓ Branch 0 taken 2032850 times.
✓ Branch 1 taken 1992452 times.
|
4025302 | if (share->idx_trans_tbl.index_count) { |
| 7863 | /* Index entry count should still match mysql_num_index */ | ||
| 7864 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2032850 times.
|
2032850 | ut_a(share->idx_trans_tbl.index_count == mysql_num_index); |
| 7865 | 2032850 | goto func_exit; | |
| 7866 | } | ||
| 7867 | |||
| 7868 | /* The number of index increased, rebuild the mapping table */ | ||
| 7869 |
2/2✓ Branch 0 taken 1597665 times.
✓ Branch 1 taken 394787 times.
|
1992452 | if (mysql_num_index > share->idx_trans_tbl.array_size) { |
| 7870 | index_mapping = reinterpret_cast<dict_index_t **>( | ||
| 7871 | 1597665 | ut::realloc_withkey(UT_NEW_THIS_FILE_PSI_KEY, index_mapping, | |
| 7872 | mysql_num_index * sizeof(*index_mapping))); | ||
| 7873 | |||
| 7874 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1597665 times.
|
1597665 | if (index_mapping == nullptr) { |
| 7875 | /* Report an error if index_mapping continues to be | ||
| 7876 | NULL and mysql_num_index is a non-zero value */ | ||
| 7877 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_TRX_XLATION_TABLE_OOM, mysql_num_index, | |
| 7878 | share->idx_trans_tbl.array_size); | ||
| 7879 | ✗ | ret = false; | |
| 7880 | ✗ | goto func_exit; | |
| 7881 | } | ||
| 7882 | |||
| 7883 | 1597665 | share->idx_trans_tbl.array_size = mysql_num_index; | |
| 7884 | } | ||
| 7885 | |||
| 7886 | /* For each index in the mysql key_info array, fetch its | ||
| 7887 | corresponding InnoDB index pointer into index_mapping | ||
| 7888 | array. */ | ||
| 7889 |
2/2✓ Branch 0 taken 3999200 times.
✓ Branch 1 taken 1992452 times.
|
5991652 | for (ulint count = 0; count < mysql_num_index; count++) { |
| 7890 | /* Fetch index pointers into index_mapping according to mysql | ||
| 7891 | index sequence */ | ||
| 7892 | 7998400 | index_mapping[count] = | |
| 7893 |
1/2✓ Branch 0 taken 3999200 times.
✗ Branch 1 not taken.
|
3999200 | dict_table_get_index_on_name(ib_table, table->key_info[count].name); |
| 7894 | |||
| 7895 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3999200 times.
|
3999200 | if (index_mapping[count] == nullptr) { |
| 7896 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_CANT_FIND_INDEX_IN_INNODB_DD, | |
| 7897 | table->key_info[count].name); | ||
| 7898 | ✗ | ret = false; | |
| 7899 | ✗ | goto func_exit; | |
| 7900 | } | ||
| 7901 | |||
| 7902 | /* Double check fetched index has the same | ||
| 7903 | column info as those in mysql key_info. */ | ||
| 7904 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3999200 times.
|
3999200 | if (!innobase_match_index_columns(&table->key_info[count], |
| 7905 |
1/2✓ Branch 0 taken 3999200 times.
✗ Branch 1 not taken.
|
3999200 | index_mapping[count])) { |
| 7906 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_INDEX_COLUMN_INFO_UNLIKE_MYSQLS, | |
| 7907 | table->key_info[count].name); | ||
| 7908 | ✗ | ret = false; | |
| 7909 | ✗ | goto func_exit; | |
| 7910 | } | ||
| 7911 | } | ||
| 7912 | |||
| 7913 | /* Successfully built the translation table */ | ||
| 7914 | 1992452 | share->idx_trans_tbl.index_count = mysql_num_index; | |
| 7915 | |||
| 7916 | 4025302 | func_exit: | |
| 7917 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4025302 times.
|
4025302 | if (!ret) { |
| 7918 | /* Build translation table failed. */ | ||
| 7919 | ✗ | ut::free(index_mapping); | |
| 7920 | |||
| 7921 | ✗ | share->idx_trans_tbl.array_size = 0; | |
| 7922 | ✗ | share->idx_trans_tbl.index_count = 0; | |
| 7923 | ✗ | index_mapping = nullptr; | |
| 7924 | } | ||
| 7925 | |||
| 7926 | 4025302 | share->idx_trans_tbl.index_mapping = index_mapping; | |
| 7927 | |||
| 7928 |
1/2✓ Branch 0 taken 4025302 times.
✗ Branch 1 not taken.
|
4025302 | dict_sys_mutex_exit(); |
| 7929 | |||
| 7930 | 4025302 | return ret; | |
| 7931 | 4025302 | } | |
| 7932 | |||
| 7933 | /** This function uses index translation table to quickly locate the | ||
| 7934 | requested index structure. | ||
| 7935 | Note we do not have mutex protection for the index translatoin table | ||
| 7936 | access, it is based on the assumption that there is no concurrent | ||
| 7937 | translation table rebuild (fter create/drop index) and DMLs that | ||
| 7938 | require index lookup. | ||
| 7939 | @return dict_index_t structure for requested index. NULL if | ||
| 7940 | fail to locate the index structure. */ | ||
| 7941 | 132327353 | static dict_index_t *innobase_index_lookup( | |
| 7942 | INNOBASE_SHARE *share, /*!< in: share structure for index | ||
| 7943 | translation table. */ | ||
| 7944 | uint keynr) /*!< in: index number for the requested | ||
| 7945 | index */ | ||
| 7946 | { | ||
| 7947 |
1/2✓ Branch 0 taken 132327419 times.
✗ Branch 1 not taken.
|
132327353 | if (share->idx_trans_tbl.index_mapping == nullptr || |
| 7948 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132327736 times.
|
132327419 | keynr >= share->idx_trans_tbl.index_count) { |
| 7949 | ✗ | return (nullptr); | |
| 7950 | } | ||
| 7951 | |||
| 7952 | 132327736 | return (share->idx_trans_tbl.index_mapping[keynr]); | |
| 7953 | } | ||
| 7954 | |||
| 7955 | /** Set the autoinc column max value. This should only be called from | ||
| 7956 | ha_innobase::open, therefore there's no need for a covering lock. */ | ||
| 7957 | 109574 | void ha_innobase::innobase_initialize_autoinc() { | |
| 7958 | ulonglong auto_inc; | ||
| 7959 | 109574 | const Field *field = table->found_next_number_field; | |
| 7960 | |||
| 7961 |
1/2✓ Branch 0 taken 109574 times.
✗ Branch 1 not taken.
|
109574 | if (field != nullptr) { |
| 7962 | 109574 | auto_inc = field->get_max_int_value(); | |
| 7963 | |||
| 7964 | /* autoinc column cannot be virtual column */ | ||
| 7965 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 109574 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 109574 times.
|
109574 | ut_ad(!innobase_is_v_fld(field)); |
| 7966 | } else { | ||
| 7967 | /* We have no idea what's been passed in to us as the | ||
| 7968 | autoinc column. We set it to the 0, effectively disabling | ||
| 7969 | updates to the table. */ | ||
| 7970 | ✗ | auto_inc = 0; | |
| 7971 | |||
| 7972 | ✗ | ib::info(ER_IB_MSG_552) << "Unable to determine the AUTOINC column name"; | |
| 7973 | } | ||
| 7974 | |||
| 7975 |
2/2✓ Branch 0 taken 91 times.
✓ Branch 1 taken 109483 times.
|
109574 | if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { |
| 7976 | /* If the recovery level is set so high that writes | ||
| 7977 | are disabled we force the AUTOINC counter to 0 | ||
| 7978 | value effectively disabling writes to the table. | ||
| 7979 | Secondly, we avoid reading the table in case the read | ||
| 7980 | results in failure due to a corrupted table/index. | ||
| 7981 | |||
| 7982 | We will not return an error to the client, so that the | ||
| 7983 | tables can be dumped with minimal hassle. If an error | ||
| 7984 | were returned in this case, the first attempt to read | ||
| 7985 | the table would fail and subsequent SELECTs would succeed. */ | ||
| 7986 | 91 | auto_inc = 0; | |
| 7987 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 109483 times.
|
109483 | } else if (field == nullptr) { |
| 7988 | /* This is a far more serious error, best to avoid | ||
| 7989 | opening the table and return failure. */ | ||
| 7990 | ✗ | my_error(ER_AUTOINC_READ_FAILED, MYF(0)); | |
| 7991 | } else { | ||
| 7992 | 109483 | dict_index_t *index = nullptr; | |
| 7993 | const char *col_name; | ||
| 7994 | uint64_t read_auto_inc; | ||
| 7995 | ulint err; | ||
| 7996 | |||
| 7997 |
2/4✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 109483 times.
✗ Branch 3 not taken.
|
109483 | update_thd(ha_thd()); |
| 7998 | |||
| 7999 | 109483 | col_name = field->field_name; | |
| 8000 | |||
| 8001 |
1/2✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
|
109483 | read_auto_inc = dict_table_autoinc_read(m_prebuilt->table); |
| 8002 | |||
| 8003 |
2/2✓ Branch 0 taken 23872 times.
✓ Branch 1 taken 85611 times.
|
109483 | if (read_auto_inc == 0) { |
| 8004 |
1/2✓ Branch 0 taken 23872 times.
✗ Branch 1 not taken.
|
23872 | index = innobase_get_index(table->s->next_number_index); |
| 8005 | |||
| 8006 | /* Execute SELECT MAX(col_name) FROM TABLE; | ||
| 8007 | This is necessary when an imported tablespace | ||
| 8008 | doesn't have a correct cfg file so autoinc | ||
| 8009 | has not been initialized, or the table is empty. */ | ||
| 8010 |
1/2✓ Branch 0 taken 23872 times.
✗ Branch 1 not taken.
|
23872 | err = row_search_max_autoinc(index, col_name, &read_auto_inc); |
| 8011 | |||
| 8012 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23872 times.
|
23872 | if (read_auto_inc > 0) { |
| 8013 | ✗ | ib::warn(ER_IB_MSG_553) | |
| 8014 | ✗ | << "Reading max(auto_inc_col) = " << read_auto_inc << " for table " | |
| 8015 | ✗ | << index->table->name << ", because there was an IMPORT" | |
| 8016 | ✗ | << " without cfg file."; | |
| 8017 | } | ||
| 8018 | |||
| 8019 | } else { | ||
| 8020 | 85611 | err = DB_SUCCESS; | |
| 8021 | } | ||
| 8022 | |||
| 8023 |
1/3✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
109483 | switch (err) { |
| 8024 | 109483 | case DB_SUCCESS: { | |
| 8025 | ulonglong col_max_value; | ||
| 8026 | |||
| 8027 |
1/2✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
|
109483 | col_max_value = field->get_max_int_value(); |
| 8028 | |||
| 8029 | /* At the this stage we do not know the increment | ||
| 8030 | nor the offset, so use a default increment of 1. */ | ||
| 8031 | |||
| 8032 |
1/2✓ Branch 0 taken 109483 times.
✗ Branch 1 not taken.
|
109483 | auto_inc = innobase_next_autoinc(read_auto_inc, 1, 1, 0, col_max_value); |
| 8033 | |||
| 8034 | 109483 | break; | |
| 8035 | } | ||
| 8036 | ✗ | case DB_RECORD_NOT_FOUND: | |
| 8037 | ✗ | ib::error(ER_IB_MSG_554) << "MySQL and InnoDB data dictionaries are" | |
| 8038 | " out of sync. Unable to find the AUTOINC" | ||
| 8039 | ✗ | " column " | |
| 8040 | ✗ | << col_name | |
| 8041 | << " in the InnoDB" | ||
| 8042 | ✗ | " table " | |
| 8043 | ✗ | << index->table->name | |
| 8044 | << ". We set" | ||
| 8045 | " the next AUTOINC column value to 0, in" | ||
| 8046 | " effect disabling the AUTOINC next value" | ||
| 8047 | ✗ | " generation."; | |
| 8048 | |||
| 8049 | ✗ | ib::info(ER_IB_MSG_555) << "You can either set the next AUTOINC" | |
| 8050 | " value explicitly using ALTER TABLE or fix" | ||
| 8051 | " the data dictionary by recreating the" | ||
| 8052 | ✗ | " table."; | |
| 8053 | |||
| 8054 | /* This will disable the AUTOINC generation. */ | ||
| 8055 | ✗ | auto_inc = 0; | |
| 8056 | |||
| 8057 | /* We want the open to succeed, so that the user can | ||
| 8058 | take corrective action. ie. reads should succeed but | ||
| 8059 | updates should fail. */ | ||
| 8060 | ✗ | err = DB_SUCCESS; | |
| 8061 | ✗ | break; | |
| 8062 | ✗ | default: | |
| 8063 | /* row_search_max_autoinc() should only return | ||
| 8064 | one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */ | ||
| 8065 | ✗ | ut_error; | |
| 8066 | } | ||
| 8067 | } | ||
| 8068 | |||
| 8069 | 109574 | dict_table_autoinc_initialize(m_prebuilt->table, auto_inc); | |
| 8070 | 109574 | } | |
| 8071 | |||
| 8072 | /** Open an InnoDB table. | ||
| 8073 | @param[in] name table name | ||
| 8074 | @param[in] open_flags flags for opening table from SQL-layer. | ||
| 8075 | @param[in] table_def dd::Table object describing table to be opened | ||
| 8076 | @retval 1 if error | ||
| 8077 | @retval 0 if success */ | ||
| 8078 | 4025379 | int ha_innobase::open(const char *name, int, uint open_flags, | |
| 8079 | const dd::Table *table_def) { | ||
| 8080 | dict_table_t *ib_table; | ||
| 8081 | char norm_name[FN_REFLEN]; | ||
| 8082 | THD *thd; | ||
| 8083 | 4025379 | bool cached = false; | |
| 8084 | |||
| 8085 |
1/2✓ Branch 0 taken 4025399 times.
✗ Branch 1 not taken.
|
4025379 | DBUG_TRACE; |
| 8086 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4025399 times.
|
4025399 | assert(table_share == table->s); |
| 8087 | |||
| 8088 |
1/2✓ Branch 0 taken 4025391 times.
✗ Branch 1 not taken.
|
4025399 | thd = ha_thd(); |
| 8089 | |||
| 8090 |
2/4✓ Branch 0 taken 4025391 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025391 times.
|
4025391 | if (!normalize_table_name(norm_name, name)) { |
| 8091 | /* purecov: begin inspected */ | ||
| 8092 | ✗ | ut_d(ut_error); | |
| 8093 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 8094 | /* purecov: end */ | ||
| 8095 | } | ||
| 8096 | |||
| 8097 | 4025391 | m_user_thd = nullptr; | |
| 8098 | 4025391 | m_share = nullptr; | |
| 8099 | |||
| 8100 | /* Will be allocated if it is needed in ::update_row() */ | ||
| 8101 | 4025391 | m_upd_buf = nullptr; | |
| 8102 | 4025391 | m_upd_buf_size = 0; | |
| 8103 | |||
| 8104 | /* Get pointer to a table object in InnoDB dictionary cache. | ||
| 8105 | For intrinsic table, get it from session private data */ | ||
| 8106 |
2/4✓ Branch 0 taken 4025395 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4025388 times.
✗ Branch 3 not taken.
|
4025391 | ib_table = thd_to_innodb_session(thd)->lookup_table_handler(norm_name); |
| 8107 | |||
| 8108 |
2/2✓ Branch 0 taken 3914192 times.
✓ Branch 1 taken 111196 times.
|
4025388 | if (ib_table == nullptr) { |
| 8109 |
3/4✓ Branch 0 taken 3785942 times.
✓ Branch 1 taken 128250 times.
✓ Branch 2 taken 3785947 times.
✗ Branch 3 not taken.
|
3914192 | DEBUG_SYNC_C("ha_innobase_open"); |
| 8110 | |||
| 8111 |
1/2✓ Branch 0 taken 3914202 times.
✗ Branch 1 not taken.
|
3914197 | dict_sys_mutex_enter(); |
| 8112 |
1/2✓ Branch 0 taken 3914202 times.
✗ Branch 1 not taken.
|
3914202 | ib_table = dict_table_check_if_in_cache_low(norm_name); |
| 8113 |
2/2✓ Branch 0 taken 3194749 times.
✓ Branch 1 taken 719453 times.
|
3914202 | if (ib_table != nullptr) { |
| 8114 |
3/4✓ Branch 0 taken 3194749 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3194747 times.
|
3194749 | if (ib_table->is_corrupted()) { |
| 8115 | /* Optionally remove this corrupted table from cache now | ||
| 8116 | if no other thread is still using it. If not, the corrupted bit | ||
| 8117 | will keep it from being used.*/ | ||
| 8118 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (ib_table->get_ref_count() == 0) { |
| 8119 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | dict_table_remove_from_cache(ib_table); |
| 8120 | } | ||
| 8121 | 2 | ib_table = nullptr; | |
| 8122 | 2 | cached = true; | |
| 8123 |
2/2✓ Branch 0 taken 7120 times.
✓ Branch 1 taken 3187627 times.
|
3194747 | } else if (ib_table->refresh_fk) { |
| 8124 |
1/2✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
|
7120 | ib_table->acquire_with_lock(); |
| 8125 | |||
| 8126 |
1/2✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
|
7120 | dict_names_t fk_tables; |
| 8127 |
1/2✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
|
7120 | dict_sys_mutex_exit(); |
| 8128 |
1/2✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
|
7120 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 8129 |
1/2✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
|
7120 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 8130 | |||
| 8131 | 21360 | dberr_t err = dd_table_load_fk( | |
| 8132 |
1/2✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
|
7120 | client, ib_table->name.m_name, nullptr, ib_table, |
| 8133 | 7120 | &table_def->table(), thd, false, | |
| 8134 |
1/2✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
|
7120 | !thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS), &fk_tables); |
| 8135 | |||
| 8136 |
1/2✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
|
7120 | dict_sys_mutex_enter(); |
| 8137 | 7120 | ib_table->refresh_fk = false; | |
| 8138 | |||
| 8139 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7120 times.
|
7120 | if (err != DB_SUCCESS) { |
| 8140 | ✗ | ib_table->release(); | |
| 8141 | ✗ | goto reload; | |
| 8142 | } | ||
| 8143 | |||
| 8144 | 7120 | cached = true; | |
| 8145 |
4/6✓ Branch 0 taken 7120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7120 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31075 times.
✓ Branch 5 taken 3156552 times.
|
3194747 | } else if (ib_table->discard_after_ddl) { |
| 8146 | 31075 | reload: | |
| 8147 |
1/2✓ Branch 0 taken 31075 times.
✗ Branch 1 not taken.
|
31075 | btr_drop_ahi_for_table(ib_table); |
| 8148 |
1/2✓ Branch 0 taken 31075 times.
✗ Branch 1 not taken.
|
31075 | dict_table_remove_from_cache(ib_table); |
| 8149 | 31075 | ib_table = nullptr; | |
| 8150 | } else { | ||
| 8151 | 3156552 | cached = true; | |
| 8152 |
2/4✓ Branch 0 taken 3156552 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3156552 times.
|
3156552 | if (!dd_table_match(ib_table, table_def)) { |
| 8153 | ✗ | dict_set_corrupted(ib_table->first_index()); | |
| 8154 | ✗ | dict_table_remove_from_cache(ib_table); | |
| 8155 | ✗ | ib_table = nullptr; | |
| 8156 | } else { | ||
| 8157 |
1/2✓ Branch 0 taken 3156552 times.
✗ Branch 1 not taken.
|
3156552 | ib_table->acquire_with_lock(); |
| 8158 | } | ||
| 8159 | } | ||
| 8160 | |||
| 8161 | /* If the table is in-memory, always get the latest | ||
| 8162 | version, in case this is open table after DDL */ | ||
| 8163 |
4/4✓ Branch 0 taken 3163672 times.
✓ Branch 1 taken 31077 times.
✓ Branch 2 taken 2964246 times.
✓ Branch 3 taken 199426 times.
|
3194749 | if (ib_table != nullptr && table_def != nullptr) { |
| 8164 |
1/2✓ Branch 0 taken 2964246 times.
✗ Branch 1 not taken.
|
2964246 | ib_table->version = dd_get_version(table_def); |
| 8165 | } | ||
| 8166 | |||
| 8167 |
2/2✓ Branch 0 taken 3163672 times.
✓ Branch 1 taken 31077 times.
|
3194749 | if (ib_table != nullptr) { |
| 8168 |
1/2✓ Branch 0 taken 3163672 times.
✗ Branch 1 not taken.
|
3163672 | dict_table_ddl_release(ib_table); |
| 8169 | } | ||
| 8170 | } | ||
| 8171 | |||
| 8172 |
1/2✓ Branch 0 taken 3914202 times.
✗ Branch 1 not taken.
|
3914202 | dict_sys_mutex_exit(); |
| 8173 | |||
| 8174 |
2/2✓ Branch 0 taken 750528 times.
✓ Branch 1 taken 3163674 times.
|
3914202 | if (!cached) { |
| 8175 |
1/2✓ Branch 0 taken 750528 times.
✗ Branch 1 not taken.
|
750528 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 8176 |
1/2✓ Branch 0 taken 750528 times.
✗ Branch 1 not taken.
|
750528 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 8177 | |||
| 8178 |
1/2✓ Branch 0 taken 750528 times.
✗ Branch 1 not taken.
|
750528 | ib_table = dd_open_table(client, table, norm_name, table_def, thd); |
| 8179 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 750526 times.
|
750528 | if (!ib_table) { |
| 8180 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | set_my_errno(ENOENT); |
| 8181 | 2 | return HA_ERR_NO_SUCH_TABLE; | |
| 8182 | } | ||
| 8183 |
2/2✓ Branch 0 taken 750526 times.
✓ Branch 1 taken 2 times.
|
750528 | } |
| 8184 | } else { | ||
| 8185 |
1/2✓ Branch 0 taken 111198 times.
✗ Branch 1 not taken.
|
111196 | ib_table->acquire(); |
| 8186 |
2/4✓ Branch 0 taken 111198 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 111198 times.
|
111198 | ut_ad(ib_table->is_intrinsic()); |
| 8187 | } | ||
| 8188 | |||
| 8189 |
2/2✓ Branch 0 taken 4025395 times.
✓ Branch 1 taken 3 times.
|
4025398 | if (ib_table != nullptr) { |
| 8190 | /* Make sure table->is_dd_table is set */ | ||
| 8191 | 4025395 | std::string db_str; | |
| 8192 | 4025396 | std::string tbl_str; | |
| 8193 |
2/4✓ Branch 0 taken 4025396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4025396 times.
✗ Branch 3 not taken.
|
4025396 | dict_name::get_table(ib_table->name.m_name, db_str, tbl_str); |
| 8194 | |||
| 8195 | 4025396 | ib_table->is_dd_table = | |
| 8196 |
4/8✓ Branch 0 taken 4025396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4025396 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4025396 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4025396 times.
✗ Branch 7 not taken.
|
4025396 | dd::get_dictionary()->is_dd_table_name(db_str.c_str(), tbl_str.c_str()); |
| 8197 | 4025396 | } | |
| 8198 | |||
| 8199 | /* m_share might hold pointers to dict table indexes without any pin. | ||
| 8200 | We must always allocate m_share after opening the dict_table_t object | ||
| 8201 | and free it before de-allocating dict_table_t to avoid race. */ | ||
| 8202 |
2/2✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 3 times.
|
4025399 | if (ib_table != nullptr) { |
| 8203 |
1/2✓ Branch 0 taken 4025396 times.
✗ Branch 1 not taken.
|
4025396 | m_share = get_share(name); |
| 8204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4025396 times.
|
4025396 | if (m_share == nullptr) { |
| 8205 | ✗ | dict_table_close(ib_table, false, false); | |
| 8206 | ✗ | return HA_ERR_SE_OUT_OF_MEMORY; | |
| 8207 | } | ||
| 8208 | |||
| 8209 |
3/10✗ Branch 0 not taken.
✓ Branch 1 taken 4025396 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4025396 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4025396 times.
|
4025396 | if (UNIV_UNLIKELY(m_share->ib_table && m_share->ib_table->is_corrupt && |
| 8210 | srv_pass_corrupt_table <= 1)) { | ||
| 8211 | ✗ | free_share_and_nullify(&m_share); | |
| 8212 | ✗ | dict_table_close(ib_table, false, false); | |
| 8213 | ✗ | return HA_ERR_CRASHED_ON_USAGE; | |
| 8214 | } | ||
| 8215 | } | ||
| 8216 | |||
| 8217 |
3/4✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025398 times.
|
8050794 | if (ib_table != nullptr && |
| 8218 |
2/2✓ Branch 0 taken 4024192 times.
✓ Branch 1 taken 1204 times.
|
4025396 | ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) && |
| 8219 |
4/6✓ Branch 0 taken 4024192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4024193 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1204 times.
✓ Branch 5 taken 4024192 times.
|
8049588 | table->s->fields != dict_table_get_n_tot_u_cols(ib_table)) || |
| 8220 | 4025397 | (DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) && | |
| 8221 |
3/4✓ Branch 0 taken 1204 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1203 times.
|
1204 | (table->s->fields != dict_table_get_n_tot_u_cols(ib_table) - 1)))) { |
| 8222 | ✗ | ib::warn(ER_IB_MSG_556) | |
| 8223 | ✗ | << "Table " << norm_name << " contains " << ib_table->get_n_user_cols() | |
| 8224 | << " user" | ||
| 8225 | ✗ | " defined columns in InnoDB, but " | |
| 8226 | ✗ | << table->s->fields | |
| 8227 | << " columns in MySQL. Please check" | ||
| 8228 | " INFORMATION_SCHEMA.INNODB_COLUMNS and " REFMAN | ||
| 8229 | "innodb-troubleshooting.html for how to resolve the" | ||
| 8230 | ✗ | " issue."; | |
| 8231 | |||
| 8232 | /* Mark this table as corrupted, so the drop table | ||
| 8233 | or force recovery can still use it, but not others. */ | ||
| 8234 | ✗ | ib_table->first_index()->type |= DICT_CORRUPT; | |
| 8235 | ✗ | free_share_and_nullify(&m_share); | |
| 8236 | ✗ | dict_table_close(ib_table, false, false); | |
| 8237 | ✗ | ib_table = nullptr; | |
| 8238 | } | ||
| 8239 | |||
| 8240 |
5/10✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025396 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4025398 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4025398 times.
|
4025398 | if (UNIV_UNLIKELY(ib_table && ib_table->is_corrupt && |
| 8241 | srv_pass_corrupt_table <= 1)) { | ||
| 8242 | ✗ | free_share_and_nullify(&m_share); | |
| 8243 | ✗ | dict_table_close(ib_table, false, false); | |
| 8244 | ✗ | return HA_ERR_CRASHED_ON_USAGE; | |
| 8245 | } | ||
| 8246 | |||
| 8247 | 8050787 | FilSpace space; | |
| 8248 |
4/6✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4025396 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4025396 times.
✗ Branch 5 not taken.
|
4025398 | if (ib_table) space = fil_space_acquire_silent(ib_table->space); |
| 8249 | |||
| 8250 | /* For encrypted table, check if the encryption info in data | ||
| 8251 | file can't be retrieved properly, mark it as corrupted. */ | ||
| 8252 | 8050794 | if (ib_table != nullptr && | |
| 8253 |
3/4✓ Branch 0 taken 4025396 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4016917 times.
✓ Branch 3 taken 8479 times.
|
4025396 | (dd_is_table_in_encrypted_tablespace(ib_table) || |
| 8254 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 4016917 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
4016917 | (ib_table->keyring_encryption_info.page0_has_crypt_data && |
| 8255 | ✗ | ib_table->keyring_encryption_info.is_encryption_in_progress())) && | |
| 8256 |
8/8✓ Branch 0 taken 4025396 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 8422 times.
✓ Branch 4 taken 53 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 53 times.
✓ Branch 7 taken 4025345 times.
|
8050794 | ib_table->ibd_file_missing && !dict_table_is_discarded(ib_table)) { |
| 8257 | /* Mark this table as corrupted, so the drop table | ||
| 8258 | or force recovery can still use it, but not others. */ | ||
| 8259 | 53 | FilSpace space; | |
| 8260 | 53 | int error = 0; | |
| 8261 |
3/6✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 53 times.
✗ Branch 5 not taken.
|
53 | if (ib_table) space = fil_space_acquire_silent(ib_table->space); |
| 8262 |
2/4✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
|
106 | if (space() == NULL && |
| 8263 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
53 | (ib_table->keyring_encryption_info.keyring_encryption_key_is_missing || |
| 8264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | ib_table->keyring_encryption_info.page0_has_crypt_data)) { |
| 8265 | /* Proper error message has been already printed by | ||
| 8266 | * Datafile::validate_first_page, thus we do not print anything here */ | ||
| 8267 | ✗ | error = HA_ERR_ENCRYPTION_KEY_MISSING; | |
| 8268 | } else { | ||
| 8269 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
53 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 8270 | 53 | error = HA_ERR_TABLE_CORRUPT; | |
| 8271 | } | ||
| 8272 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
53 | dict_table_close(ib_table, false, false); |
| 8273 | 53 | ib_table = nullptr; | |
| 8274 | |||
| 8275 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
53 | free_share_and_nullify(&m_share); |
| 8276 | 53 | return error; | |
| 8277 | 53 | } | |
| 8278 | |||
| 8279 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4025343 times.
|
4025345 | if (nullptr == ib_table) { |
| 8280 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | ib::warn(ER_IB_MSG_557) |
| 8281 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | << "Cannot open table " << norm_name << TROUBLESHOOTING_MSG; |
| 8282 | |||
| 8283 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | set_my_errno(ENOENT); |
| 8284 | |||
| 8285 | 2 | return HA_ERR_NO_SUCH_TABLE; | |
| 8286 | } | ||
| 8287 | |||
| 8288 |
1/2✓ Branch 0 taken 4025342 times.
✗ Branch 1 not taken.
|
4025343 | innobase_copy_frm_flags_from_table_share(ib_table, table->s); |
| 8289 | |||
| 8290 |
1/2✓ Branch 0 taken 4025343 times.
✗ Branch 1 not taken.
|
4025342 | dict_stats_init(ib_table); |
| 8291 | |||
| 8292 | 4025343 | MONITOR_INC(MONITOR_TABLE_OPEN); | |
| 8293 | |||
| 8294 | bool no_tablespace; | ||
| 8295 | |||
| 8296 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 4025294 times.
|
4025343 | if (dict_table_is_discarded(ib_table)) { |
| 8297 | /* If the op is an IMPORT, open the space without this warning. */ | ||
| 8298 |
3/4✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 9 times.
|
49 | if (thd_tablespace_op(thd) != Alter_info::ALTER_IMPORT_TABLESPACE) { |
| 8299 | 40 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_TABLESPACE_DISCARDED, | |
| 8300 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | table->s->table_name.str); |
| 8301 | } | ||
| 8302 | |||
| 8303 | /* Allow an open because a proper DISCARD should have set | ||
| 8304 | all the flags and index root page numbers to FIL_NULL that | ||
| 8305 | should prevent any DML from running but it should allow DDL | ||
| 8306 | operations. */ | ||
| 8307 | 49 | no_tablespace = false; | |
| 8308 | |||
| 8309 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4025246 times.
|
4025294 | } else if (ib_table->ibd_file_missing) { |
| 8310 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_TABLESPACE_MISSING, norm_name); |
| 8311 | |||
| 8312 | /* This means we have no idea what happened to the tablespace | ||
| 8313 | file, best to play it safe. */ | ||
| 8314 | |||
| 8315 | 48 | no_tablespace = true; | |
| 8316 | } else { | ||
| 8317 | 4025246 | no_tablespace = false; | |
| 8318 | } | ||
| 8319 | |||
| 8320 |
7/8✓ Branch 0 taken 4025343 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4025199 times.
✓ Branch 3 taken 144 times.
✓ Branch 4 taken 47 times.
✓ Branch 5 taken 4025152 times.
✓ Branch 6 taken 47 times.
✓ Branch 7 taken 4025296 times.
|
4025343 | if (!thd_tablespace_op(thd) && no_tablespace) { |
| 8321 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | free_share_and_nullify(&m_share); |
| 8322 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | set_my_errno(ENOENT); |
| 8323 | |||
| 8324 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | dict_table_close(ib_table, false, false); |
| 8325 | |||
| 8326 | 47 | return HA_ERR_TABLESPACE_MISSING; | |
| 8327 | } | ||
| 8328 | |||
| 8329 |
1/2✓ Branch 0 taken 4025279 times.
✗ Branch 1 not taken.
|
4025296 | m_prebuilt = row_create_prebuilt(ib_table, table->s->reclength); |
| 8330 | |||
| 8331 | 4025279 | m_prebuilt->default_rec = table->s->default_values; | |
| 8332 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4025296 times.
|
4025279 | ut_ad(m_prebuilt->default_rec); |
| 8333 | |||
| 8334 | 4025296 | m_prebuilt->m_mysql_table = table; | |
| 8335 | 4025296 | m_prebuilt->m_mysql_handler = this; | |
| 8336 | |||
| 8337 |
3/4✓ Branch 0 taken 4025296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 111198 times.
✓ Branch 3 taken 3914098 times.
|
4025296 | if (ib_table->is_intrinsic()) { |
| 8338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 111198 times.
|
111198 | ut_ad(open_flags & HA_OPEN_INTERNAL_TABLE); |
| 8339 | |||
| 8340 |
1/2✓ Branch 0 taken 111198 times.
✗ Branch 1 not taken.
|
111198 | m_prebuilt->m_temp_read_shared = table_share->ref_count() >= 2; |
| 8341 | |||
| 8342 |
2/2✓ Branch 0 taken 336 times.
✓ Branch 1 taken 110862 times.
|
111198 | if (m_prebuilt->m_temp_read_shared) { |
| 8343 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 224 times.
|
336 | if (ib_table->temp_prebuilt == nullptr) { |
| 8344 | 112 | ib_table->temp_prebuilt = | |
| 8345 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | ut::new_withkey<temp_prebuilt_vec>(UT_NEW_THIS_FILE_PSI_KEY); |
| 8346 | } | ||
| 8347 | |||
| 8348 |
1/2✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
|
336 | ib_table->temp_prebuilt->push_back(m_prebuilt); |
| 8349 | } | ||
| 8350 | 111198 | m_prebuilt->m_temp_tree_modified = false; | |
| 8351 | } | ||
| 8352 | |||
| 8353 | 4025296 | key_used_on_scan = table_share->primary_key; | |
| 8354 | |||
| 8355 |
2/2✓ Branch 0 taken 43273 times.
✓ Branch 1 taken 3982023 times.
|
4025296 | if (ib_table->n_v_cols) { |
| 8356 |
1/2✓ Branch 0 taken 43273 times.
✗ Branch 1 not taken.
|
43273 | dict_sys_mutex_enter(); |
| 8357 |
2/2✓ Branch 0 taken 22619 times.
✓ Branch 1 taken 20654 times.
|
43273 | if (ib_table->vc_templ == nullptr) { |
| 8358 | 22619 | ib_table->vc_templ = | |
| 8359 |
1/2✓ Branch 0 taken 22619 times.
✗ Branch 1 not taken.
|
22619 | ut::new_withkey<dict_vcol_templ_t>(UT_NEW_THIS_FILE_PSI_KEY); |
| 8360 | 22619 | ib_table->vc_templ->vtempl = nullptr; | |
| 8361 |
2/2✓ Branch 0 taken 19870 times.
✓ Branch 1 taken 784 times.
|
20654 | } else if (ib_table->get_ref_count() == 1) { |
| 8362 | /* Clean and refresh the template if no one else | ||
| 8363 | get hold on it */ | ||
| 8364 |
1/2✓ Branch 0 taken 19870 times.
✗ Branch 1 not taken.
|
19870 | dict_free_vc_templ(ib_table->vc_templ); |
| 8365 | 19870 | ib_table->vc_templ->vtempl = nullptr; | |
| 8366 | } | ||
| 8367 | |||
| 8368 |
2/2✓ Branch 0 taken 42489 times.
✓ Branch 1 taken 784 times.
|
43273 | if (ib_table->vc_templ->vtempl == nullptr) { |
| 8369 | 42489 | innobase_build_v_templ(table, ib_table, ib_table->vc_templ, nullptr, true, | |
| 8370 |
1/2✓ Branch 0 taken 42489 times.
✗ Branch 1 not taken.
|
42489 | m_share->table_name); |
| 8371 | } | ||
| 8372 | |||
| 8373 |
1/2✓ Branch 0 taken 43273 times.
✗ Branch 1 not taken.
|
43273 | dict_sys_mutex_exit(); |
| 8374 | } | ||
| 8375 | |||
| 8376 |
2/4✓ Branch 0 taken 4025296 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025296 times.
|
4025296 | if (!innobase_build_index_translation(table, ib_table, m_share)) { |
| 8377 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_CANT_BUILD_INDEX_XLATION_TABLE_FOR, name); | |
| 8378 | } | ||
| 8379 | |||
| 8380 | /* Allocate a buffer for a 'row reference'. A row reference is | ||
| 8381 | a string of bytes of length ref_length which uniquely specifies | ||
| 8382 | a row in our table. Note that MySQL may also compare two row | ||
| 8383 | references for equality by doing a simple memcmp on the strings | ||
| 8384 | of length ref_length! */ | ||
| 8385 | |||
| 8386 |
3/4✓ Branch 0 taken 4025296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3398836 times.
✓ Branch 3 taken 626460 times.
|
4025296 | if (!row_table_got_default_clust_index(ib_table)) { |
| 8387 | 3398836 | m_prebuilt->clust_index_was_generated = false; | |
| 8388 | |||
| 8389 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3398836 times.
|
3398836 | if (table_share->is_missing_primary_key()) { |
| 8390 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_PK_NOT_IN_MYSQL, name); | |
| 8391 | |||
| 8392 | /* This mismatch could cause further problems | ||
| 8393 | if not attended, bring this to the user's attention | ||
| 8394 | by printing a warning in addition to log a message | ||
| 8395 | in the errorlog */ | ||
| 8396 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_SUCH_INDEX, | |
| 8397 | "InnoDB: Table %s has a" | ||
| 8398 | " primary key in InnoDB data" | ||
| 8399 | " dictionary, but not in" | ||
| 8400 | " MySQL!", | ||
| 8401 | name); | ||
| 8402 | |||
| 8403 | /* If table_share->is_missing_primary_key(), | ||
| 8404 | the table_share->primary_key | ||
| 8405 | value could be out of bound if continue to index | ||
| 8406 | into key_info[] array. Find InnoDB primary index, | ||
| 8407 | and assign its key_length to ref_length. | ||
| 8408 | In addition, since MySQL indexes are sorted starting | ||
| 8409 | with primary index, unique index etc., initialize | ||
| 8410 | ref_length to the first index key length in | ||
| 8411 | case we fail to find InnoDB cluster index. | ||
| 8412 | |||
| 8413 | Please note, this will not resolve the primary | ||
| 8414 | index mismatch problem, other side effects are | ||
| 8415 | possible if users continue to use the table. | ||
| 8416 | However, we allow this table to be opened so | ||
| 8417 | that user can adopt necessary measures for the | ||
| 8418 | mismatch while still being accessible to the table | ||
| 8419 | date. */ | ||
| 8420 | ✗ | if (!table->key_info) { | |
| 8421 | ✗ | ut_ad(!table->s->keys); | |
| 8422 | ✗ | ref_length = 0; | |
| 8423 | } else { | ||
| 8424 | ✗ | ref_length = table->key_info[0].key_length; | |
| 8425 | } | ||
| 8426 | |||
| 8427 | /* Find corresponding cluster index | ||
| 8428 | key length in MySQL's key_info[] array */ | ||
| 8429 | ✗ | for (uint i = 0; i < table->s->keys; i++) { | |
| 8430 | dict_index_t *index; | ||
| 8431 | ✗ | index = innobase_get_index(i); | |
| 8432 | ✗ | if (index->is_clustered()) { | |
| 8433 | ✗ | ref_length = table->key_info[i].key_length; | |
| 8434 | } | ||
| 8435 | } | ||
| 8436 | } else { | ||
| 8437 | /* MySQL allocates the buffer for ref. | ||
| 8438 | key_info->key_length includes space for all key | ||
| 8439 | columns + one byte for each column that may be | ||
| 8440 | NULL. ref_length must be as exact as possible to | ||
| 8441 | save space, because all row reference buffers are | ||
| 8442 | allocated based on ref_length. */ | ||
| 8443 | |||
| 8444 | 3398836 | ref_length = table->key_info[table_share->primary_key].key_length; | |
| 8445 | } | ||
| 8446 | } else { | ||
| 8447 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 626460 times.
|
626460 | if (!table_share->is_missing_primary_key()) { |
| 8448 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_PK_ONLY_IN_MYSQL, name); | |
| 8449 | |||
| 8450 | /* This mismatch could cause further problems | ||
| 8451 | if not attended, bring this to the user attention | ||
| 8452 | by printing a warning in addition to log a message | ||
| 8453 | in the errorlog */ | ||
| 8454 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_SUCH_INDEX, | |
| 8455 | "InnoDB: Table %s has no" | ||
| 8456 | " primary key in InnoDB data" | ||
| 8457 | " dictionary, but has one in" | ||
| 8458 | " MySQL!", | ||
| 8459 | name); | ||
| 8460 | } | ||
| 8461 | |||
| 8462 | 626460 | m_prebuilt->clust_index_was_generated = true; | |
| 8463 | |||
| 8464 | 626460 | ref_length = DATA_ROW_ID_LEN; | |
| 8465 | |||
| 8466 | /* If we automatically created the clustered index, then | ||
| 8467 | MySQL does not know about it, and MySQL must NOT be aware | ||
| 8468 | of the index used on scan, to make it avoid checking if we | ||
| 8469 | update the column of the index. That is why we assert below | ||
| 8470 | that key_used_on_scan is the undefined value MAX_KEY. | ||
| 8471 | The column is the row id in the automatical generation case, | ||
| 8472 | and it will never be updated anyway. */ | ||
| 8473 | |||
| 8474 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 626460 times.
|
626460 | if (key_used_on_scan != MAX_KEY) { |
| 8475 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_CLUSTERED_INDEX_PRIVATE, name, | |
| 8476 | (ulong)key_used_on_scan); | ||
| 8477 | } | ||
| 8478 | } | ||
| 8479 | |||
| 8480 | /* Index block size in InnoDB: used by MySQL in query optimization */ | ||
| 8481 | 4025296 | stats.block_size = UNIV_PAGE_SIZE; | |
| 8482 | |||
| 8483 | /* Only if the table has an AUTOINC column. */ | ||
| 8484 |
4/4✓ Branch 0 taken 4025295 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4025246 times.
✓ Branch 3 taken 49 times.
|
4025296 | if (m_prebuilt->table != nullptr && !m_prebuilt->table->ibd_file_missing && |
| 8485 |
2/2✓ Branch 0 taken 1483897 times.
✓ Branch 1 taken 2541349 times.
|
4025246 | table->found_next_number_field != NULL) { |
| 8486 | 1483897 | dict_table_t *ib_table = m_prebuilt->table; | |
| 8487 | |||
| 8488 |
1/2✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
|
1483897 | dict_table_autoinc_lock(ib_table); |
| 8489 | |||
| 8490 |
1/2✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
|
1483898 | uint64_t autoinc = dict_table_autoinc_read(ib_table); |
| 8491 | 1483898 | uint64_t autoinc_persisted = 0; | |
| 8492 | |||
| 8493 |
1/2✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
|
1483898 | mutex_enter(ib_table->autoinc_persisted_mutex); |
| 8494 | 1483898 | autoinc_persisted = ib_table->autoinc_persisted; | |
| 8495 |
1/2✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
|
1483898 | mutex_exit(ib_table->autoinc_persisted_mutex); |
| 8496 | |||
| 8497 | /* Since a table can already be "open" in InnoDB's internal | ||
| 8498 | data dictionary, we only init the autoinc counter once, the | ||
| 8499 | first time the table is loaded. We can safely reuse the | ||
| 8500 | autoinc value from a previous MySQL open. */ | ||
| 8501 |
4/4✓ Branch 0 taken 1459986 times.
✓ Branch 1 taken 23912 times.
✓ Branch 2 taken 85662 times.
✓ Branch 3 taken 1374324 times.
|
1483898 | if (autoinc == 0 || autoinc == autoinc_persisted) { |
| 8502 | /* If autoinc is 0, it means the counter was never | ||
| 8503 | used or imported from a tablespace without .cfg file. | ||
| 8504 | We have to search the index to get proper counter. | ||
| 8505 | If only the second condition is true, it means it's | ||
| 8506 | the first time open for the table, we just want to | ||
| 8507 | calculate the next counter */ | ||
| 8508 |
1/2✓ Branch 0 taken 109574 times.
✗ Branch 1 not taken.
|
109574 | innobase_initialize_autoinc(); |
| 8509 | } | ||
| 8510 | |||
| 8511 |
1/2✓ Branch 0 taken 1483898 times.
✗ Branch 1 not taken.
|
1483898 | dict_table_autoinc_set_col_pos( |
| 8512 | 1483898 | ib_table, table->found_next_number_field->field_index()); | |
| 8513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1483898 times.
|
1483898 | ut_ad(dict_table_has_autoinc_col(ib_table)); |
| 8514 | |||
| 8515 |
1/2✓ Branch 0 taken 1483896 times.
✗ Branch 1 not taken.
|
1483898 | dict_table_autoinc_unlock(ib_table); |
| 8516 | } | ||
| 8517 | |||
| 8518 | /* Set plugin parser for fulltext index */ | ||
| 8519 |
2/2✓ Branch 0 taken 10099122 times.
✓ Branch 1 taken 4025296 times.
|
14124418 | for (uint i = 0; i < table->s->keys; i++) { |
| 8520 |
2/2✓ Branch 0 taken 1254 times.
✓ Branch 1 taken 10097868 times.
|
10099122 | if (table->key_info[i].flags & HA_USES_PARSER) { |
| 8521 |
1/2✓ Branch 0 taken 1254 times.
✗ Branch 1 not taken.
|
1254 | dict_index_t *index = innobase_get_index(i); |
| 8522 | 1254 | plugin_ref parser = table->key_info[i].parser; | |
| 8523 | |||
| 8524 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1254 times.
|
1254 | ut_ad(index->type & DICT_FTS); |
| 8525 | 1254 | index->parser = | |
| 8526 | 1254 | static_cast<st_mysql_ftparser *>(plugin_decl(parser)->info); | |
| 8527 | |||
| 8528 | 1254 | index->is_ngram = strncmp(plugin_name(parser)->str, FTS_NGRAM_PARSER_NAME, | |
| 8529 | 1254 | plugin_name(parser)->length) == 0; | |
| 8530 | |||
| 8531 |
3/4✓ Branch 0 taken 1255 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1251 times.
|
1254 | DBUG_EXECUTE_IF("fts_instrument_use_default_parser", |
| 8532 | index->parser = &fts_default_parser;); | ||
| 8533 | } | ||
| 8534 | } | ||
| 8535 | |||
| 8536 |
1/2✓ Branch 0 taken 4025294 times.
✗ Branch 1 not taken.
|
4025296 | info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); |
| 8537 | |||
| 8538 | dberr_t err = | ||
| 8539 |
1/2✓ Branch 0 taken 4025277 times.
✗ Branch 1 not taken.
|
4025294 | dict_set_compression(m_prebuilt->table, table->s->compress.str, false); |
| 8540 | |||
| 8541 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3566383 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 458893 times.
|
4025277 | switch (err) { |
| 8542 | 1 | case DB_NOT_FOUND: | |
| 8543 | case DB_UNSUPPORTED: | ||
| 8544 | /* We will do another check before the create | ||
| 8545 | table and push the error to the client there. */ | ||
| 8546 | 1 | break; | |
| 8547 | |||
| 8548 | 3566383 | case DB_IO_NO_PUNCH_HOLE_TABLESPACE: | |
| 8549 | /* We did the check in the 'if' above. */ | ||
| 8550 | |||
| 8551 | case DB_IO_NO_PUNCH_HOLE_FS: | ||
| 8552 | /* During open we can't check whether the FS supports | ||
| 8553 | punch hole or not, at least on Linux. */ | ||
| 8554 | 3566383 | break; | |
| 8555 | |||
| 8556 | ✗ | default: | |
| 8557 | ✗ | ut_error; | |
| 8558 | |||
| 8559 | 458893 | case DB_SUCCESS: | |
| 8560 | 458893 | break; | |
| 8561 | } | ||
| 8562 | |||
| 8563 | #ifdef UNIV_DEBUG | ||
| 8564 | fts_aux_table_t aux_table; | ||
| 8565 | |||
| 8566 |
2/4✓ Branch 0 taken 4025281 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025281 times.
|
4025277 | if (fts_is_aux_table_name(&aux_table, norm_name, strlen(norm_name))) { |
| 8567 | ✗ | ut_ad(m_prebuilt->table->is_fts_aux()); | |
| 8568 | } | ||
| 8569 | #endif /* UNIV_DEBUG */ | ||
| 8570 | |||
| 8571 |
2/4✓ Branch 0 taken 4025290 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4025290 times.
|
4025281 | if (m_prebuilt->table->is_fts_aux()) { |
| 8572 | ✗ | dict_table_close(m_prebuilt->table, false, false); | |
| 8573 | } | ||
| 8574 | |||
| 8575 | 4025287 | return 0; | |
| 8576 | 4025400 | } | |
| 8577 | |||
| 8578 | 318820 | handler *ha_innobase::clone(const char *name, /*!< in: table name */ | |
| 8579 | MEM_ROOT *mem_root) /*!< in: memory context */ | ||
| 8580 | { | ||
| 8581 |
1/2✓ Branch 0 taken 318820 times.
✗ Branch 1 not taken.
|
318820 | DBUG_TRACE; |
| 8582 | |||
| 8583 | ha_innobase *new_handler = | ||
| 8584 |
3/4✓ Branch 0 taken 318820 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318819 times.
✓ Branch 3 taken 1 times.
|
318820 | dynamic_cast<ha_innobase *>(handler::clone(name, mem_root)); |
| 8585 | |||
| 8586 |
2/2✓ Branch 0 taken 318819 times.
✓ Branch 1 taken 1 times.
|
318820 | if (new_handler != nullptr) { |
| 8587 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 318819 times.
|
318819 | assert(new_handler->m_prebuilt != nullptr); |
| 8588 | |||
| 8589 | 318819 | new_handler->m_prebuilt->select_lock_type = m_prebuilt->select_lock_type; | |
| 8590 | } | ||
| 8591 | |||
| 8592 | 318820 | return new_handler; | |
| 8593 | 318820 | } | |
| 8594 | |||
| 8595 | 1856768 | uint ha_innobase::max_supported_key_part_length( | |
| 8596 | HA_CREATE_INFO *create_info) const { | ||
| 8597 | /* A table format specific index column length check will be performed | ||
| 8598 | at ha_innobase::add_index() and row_create_index_for_mysql() */ | ||
| 8599 |
2/2✓ Branch 0 taken 6191 times.
✓ Branch 1 taken 1850577 times.
|
1856768 | switch (create_info->row_type) { |
| 8600 | 6191 | case ROW_TYPE_REDUNDANT: | |
| 8601 | case ROW_TYPE_COMPACT: | ||
| 8602 | 6191 | return (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1); | |
| 8603 | break; | ||
| 8604 | 1850577 | default: | |
| 8605 | 1850577 | return (REC_VERSION_56_MAX_INDEX_COL_LEN); | |
| 8606 | } | ||
| 8607 | } | ||
| 8608 | |||
| 8609 | /** Closes a handle to an InnoDB table. | ||
| 8610 | @return 0 */ | ||
| 8611 | |||
| 8612 | 3916977 | int ha_innobase::close() { | |
| 8613 |
1/2✓ Branch 0 taken 3916982 times.
✗ Branch 1 not taken.
|
3916977 | DBUG_TRACE; |
| 8614 | |||
| 8615 |
2/2✓ Branch 0 taken 336 times.
✓ Branch 1 taken 3916646 times.
|
3916982 | if (m_prebuilt->m_temp_read_shared) { |
| 8616 | 336 | temp_prebuilt_vec *vec = m_prebuilt->table->temp_prebuilt; | |
| 8617 |
2/4✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
|
336 | ut_ad(m_prebuilt->table->is_intrinsic()); |
| 8618 |
2/4✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
✗ Branch 3 not taken.
|
336 | vec->erase(std::remove(vec->begin(), vec->end(), m_prebuilt), vec->end()); |
| 8619 | } | ||
| 8620 | |||
| 8621 |
1/2✓ Branch 0 taken 3916982 times.
✗ Branch 1 not taken.
|
3916982 | free_share_and_nullify(&m_share); |
| 8622 | |||
| 8623 |
1/2✓ Branch 0 taken 3916982 times.
✗ Branch 1 not taken.
|
3916982 | row_prebuilt_free(m_prebuilt, false); |
| 8624 | |||
| 8625 |
2/2✓ Branch 0 taken 197506 times.
✓ Branch 1 taken 3719476 times.
|
3916982 | if (m_upd_buf != nullptr) { |
| 8626 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 197506 times.
|
197506 | ut_ad(m_upd_buf_size != 0); |
| 8627 |
1/2✓ Branch 0 taken 197506 times.
✗ Branch 1 not taken.
|
197506 | my_free(m_upd_buf); |
| 8628 | 197506 | m_upd_buf = nullptr; | |
| 8629 | 197506 | m_upd_buf_size = 0; | |
| 8630 | } | ||
| 8631 | |||
| 8632 | 3916982 | MONITOR_INC(MONITOR_TABLE_CLOSE); | |
| 8633 | |||
| 8634 | /* Tell InnoDB server that there might be work for | ||
| 8635 | utility threads: */ | ||
| 8636 | |||
| 8637 |
1/2✓ Branch 0 taken 3916982 times.
✗ Branch 1 not taken.
|
3916982 | srv_active_wake_master_thread(); |
| 8638 | |||
| 8639 | 3916982 | return 0; | |
| 8640 | 3916982 | } | |
| 8641 | |||
| 8642 | /* The following accessor functions should really be inside MySQL code! */ | ||
| 8643 | |||
| 8644 | /** Gets field offset for a field in a table. | ||
| 8645 | @param[in] table MySQL table object | ||
| 8646 | @param[in] field MySQL field object | ||
| 8647 | @return offset */ | ||
| 8648 | 2302554716 | static inline uint get_field_offset(const TABLE *table, const Field *field) { | |
| 8649 | 2302554716 | return field->offset(table->record[0]); | |
| 8650 | } | ||
| 8651 | |||
| 8652 | #ifdef WITH_WSREP | ||
| 8653 | 3565 | int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, | |
| 8654 | unsigned char *str, unsigned int str_length, | ||
| 8655 | unsigned int buf_length) { | ||
| 8656 | CHARSET_INFO *charset; | ||
| 8657 | enum_field_types mysql_tp; | ||
| 8658 | 3565 | int ret_length = str_length; | |
| 8659 | |||
| 8660 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3565 times.
|
3565 | assert(str_length != UNIV_SQL_NULL); |
| 8661 | |||
| 8662 | 3565 | mysql_tp = (enum_field_types)mysql_type; | |
| 8663 | |||
| 8664 |
1/3✓ Branch 0 taken 3565 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
3565 | switch (mysql_tp) { |
| 8665 | 3565 | case MYSQL_TYPE_BIT: | |
| 8666 | case MYSQL_TYPE_STRING: | ||
| 8667 | case MYSQL_TYPE_VAR_STRING: | ||
| 8668 | case MYSQL_TYPE_TINY_BLOB: | ||
| 8669 | case MYSQL_TYPE_MEDIUM_BLOB: | ||
| 8670 | case MYSQL_TYPE_BLOB: | ||
| 8671 | case MYSQL_TYPE_LONG_BLOB: | ||
| 8672 | case MYSQL_TYPE_VARCHAR: { | ||
| 8673 | 3565 | uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; | |
| 8674 | 3565 | uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN; | |
| 8675 | |||
| 8676 | /* Use the charset number to pick the right charset struct for | ||
| 8677 | the comparison. Since the MySQL function get_charset may be | ||
| 8678 | slow before Bar removes the mutex operation there, we first | ||
| 8679 | look at 2 common charsets directly. */ | ||
| 8680 | |||
| 8681 |
2/2✓ Branch 0 taken 3529 times.
✓ Branch 1 taken 36 times.
|
3565 | if (charset_number == default_charset_info->number) { |
| 8682 | 3529 | charset = default_charset_info; | |
| 8683 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
|
36 | } else if (charset_number == my_charset_latin1.number) { |
| 8684 | 24 | charset = &my_charset_latin1; | |
| 8685 | } else { | ||
| 8686 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | charset = get_charset(charset_number, MYF(MY_WME)); |
| 8687 | |||
| 8688 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (charset == NULL) { |
| 8689 | ✗ | sql_print_error( | |
| 8690 | "InnoDB needs charset %lu for doing " | ||
| 8691 | "a comparison, but MySQL cannot " | ||
| 8692 | "find that charset.", | ||
| 8693 | (ulong)charset_number); | ||
| 8694 | ✗ | ut_a(0); | |
| 8695 | } | ||
| 8696 | } | ||
| 8697 | |||
| 8698 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3565 times.
|
3565 | ut_a(str_length <= tmp_length); |
| 8699 | 3565 | memcpy(tmp_str, str, str_length); | |
| 8700 | |||
| 8701 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3565 times.
|
3565 | if (wsrep_protocol_version < 3) { |
| 8702 | ✗ | tmp_length = charset->coll->strnxfrm( | |
| 8703 | charset, str, str_length, str_length, tmp_str, tmp_length, 0); | ||
| 8704 | ✗ | assert(tmp_length <= str_length); | |
| 8705 | } else { | ||
| 8706 | /* strnxfrm will expand the destination string, | ||
| 8707 | protocols < 3 truncated the sorted sring | ||
| 8708 | protocols >= 3 gets full sorted sring */ | ||
| 8709 |
1/2✓ Branch 0 taken 3565 times.
✗ Branch 1 not taken.
|
3565 | tmp_length = charset->coll->strnxfrm( |
| 8710 | charset, str, buf_length, str_length, tmp_str, str_length, 0); | ||
| 8711 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3565 times.
|
3565 | assert(tmp_length <= buf_length); |
| 8712 | 3565 | ret_length = tmp_length; | |
| 8713 | } | ||
| 8714 | 3565 | break; | |
| 8715 | } | ||
| 8716 | ✗ | case MYSQL_TYPE_DECIMAL: | |
| 8717 | case MYSQL_TYPE_TINY: | ||
| 8718 | case MYSQL_TYPE_SHORT: | ||
| 8719 | case MYSQL_TYPE_LONG: | ||
| 8720 | case MYSQL_TYPE_FLOAT: | ||
| 8721 | case MYSQL_TYPE_DOUBLE: | ||
| 8722 | case MYSQL_TYPE_NULL: | ||
| 8723 | case MYSQL_TYPE_TIMESTAMP: | ||
| 8724 | case MYSQL_TYPE_LONGLONG: | ||
| 8725 | case MYSQL_TYPE_INT24: | ||
| 8726 | case MYSQL_TYPE_DATE: | ||
| 8727 | case MYSQL_TYPE_TIME: | ||
| 8728 | case MYSQL_TYPE_DATETIME: | ||
| 8729 | case MYSQL_TYPE_YEAR: | ||
| 8730 | case MYSQL_TYPE_NEWDATE: | ||
| 8731 | case MYSQL_TYPE_NEWDECIMAL: | ||
| 8732 | case MYSQL_TYPE_ENUM: | ||
| 8733 | case MYSQL_TYPE_SET: | ||
| 8734 | case MYSQL_TYPE_GEOMETRY: | ||
| 8735 | ✗ | break; | |
| 8736 | ✗ | default: | |
| 8737 | ✗ | break; | |
| 8738 | } | ||
| 8739 | |||
| 8740 | 3565 | return ret_length; | |
| 8741 | } | ||
| 8742 | |||
| 8743 | /** Stores a key value for a row to a buffer. | ||
| 8744 | @return key value length as stored in buff */ | ||
| 8745 | 2796376 | uint wsrep_store_key_val_for_row(THD *thd, TABLE *table, uint keynr, char *buff, | |
| 8746 | uint buff_len, const uchar *record, | ||
| 8747 | bool *key_is_null, row_prebuilt_t *prebuilt) { | ||
| 8748 | 2796376 | KEY *key_info = table->key_info + keynr; | |
| 8749 | 2796376 | KEY_PART_INFO *key_part = key_info->key_part; | |
| 8750 | 2796376 | KEY_PART_INFO *end = key_part + key_info->user_defined_key_parts; | |
| 8751 | 2796376 | char *buff_start = buff; | |
| 8752 | enum_field_types mysql_type; | ||
| 8753 | Field *field; | ||
| 8754 | 2796376 | uint buff_space = buff_len; | |
| 8755 | |||
| 8756 |
1/2✓ Branch 0 taken 2796376 times.
✗ Branch 1 not taken.
|
2796376 | DBUG_ENTER("wsrep_store_key_val_for_row"); |
| 8757 | |||
| 8758 | 2796376 | memset(buff, 0, buff_len); | |
| 8759 | 2796376 | *key_is_null = true; | |
| 8760 | |||
| 8761 |
2/2✓ Branch 0 taken 2796422 times.
✓ Branch 1 taken 2796376 times.
|
5592798 | for (; key_part != end; key_part++) { |
| 8762 | 2796422 | uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; | |
| 8763 | 2796422 | bool part_is_null = false; | |
| 8764 | |||
| 8765 |
2/2✓ Branch 0 taken 3143 times.
✓ Branch 1 taken 2793279 times.
|
2796422 | if (key_part->null_bit) { |
| 8766 |
1/2✓ Branch 0 taken 3143 times.
✗ Branch 1 not taken.
|
3143 | if (buff_space > 0) { |
| 8767 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3140 times.
|
3143 | if (record[key_part->null_offset] & key_part->null_bit) { |
| 8768 | 3 | *buff = 1; | |
| 8769 | 3 | part_is_null = true; | |
| 8770 | } else { | ||
| 8771 | 3140 | *buff = 0; | |
| 8772 | } | ||
| 8773 | |||
| 8774 | 3143 | buff++; | |
| 8775 | 3143 | buff_space--; | |
| 8776 | } else { | ||
| 8777 | ✗ | fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd)); | |
| 8778 | } | ||
| 8779 | } | ||
| 8780 | |||
| 8781 |
2/2✓ Branch 0 taken 2796419 times.
✓ Branch 1 taken 3 times.
|
2796422 | if (!part_is_null) *key_is_null = false; |
| 8782 | |||
| 8783 | 2796422 | field = key_part->field; | |
| 8784 |
1/2✓ Branch 0 taken 2796422 times.
✗ Branch 1 not taken.
|
2796422 | mysql_type = field->type(); |
| 8785 | |||
| 8786 |
2/2✓ Branch 0 taken 3559 times.
✓ Branch 1 taken 2792863 times.
|
2796422 | if (mysql_type == MYSQL_TYPE_VARCHAR) { |
| 8787 | /* >= 5.0.3 true VARCHAR */ | ||
| 8788 | ulint lenlen; | ||
| 8789 | ulint len; | ||
| 8790 | const byte *data; | ||
| 8791 | ulint key_len; | ||
| 8792 | ulint true_len; | ||
| 8793 | const CHARSET_INFO *cs; | ||
| 8794 | 3559 | int error = 0; | |
| 8795 | |||
| 8796 | 3559 | key_len = key_part->length; | |
| 8797 | |||
| 8798 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3559 times.
|
3559 | if (part_is_null) { |
| 8799 | ✗ | true_len = key_len + 2; | |
| 8800 | ✗ | if (true_len > buff_space) { | |
| 8801 | ✗ | fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd)); | |
| 8802 | ✗ | true_len = buff_space; | |
| 8803 | } | ||
| 8804 | ✗ | buff += true_len; | |
| 8805 | ✗ | buff_space -= true_len; | |
| 8806 | ✗ | continue; | |
| 8807 | } | ||
| 8808 |
1/2✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
|
3559 | cs = field->charset(); |
| 8809 | |||
| 8810 |
1/2✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
|
3559 | lenlen = (ulint)(((Field_varstring *)field)->get_length_bytes()); |
| 8811 | |||
| 8812 | 7118 | data = row_mysql_read_true_varchar( | |
| 8813 |
1/2✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
|
3559 | &len, (byte *)(record + (ulint)get_field_offset(table, field)), |
| 8814 | lenlen); | ||
| 8815 | |||
| 8816 | 3559 | true_len = len; | |
| 8817 | |||
| 8818 | /* For multi byte character sets we need to calculate | ||
| 8819 | the true length of the key */ | ||
| 8820 | |||
| 8821 |
3/4✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3534 times.
✓ Branch 3 taken 25 times.
|
3559 | if (len > 0 && cs->mbmaxlen > 1) { |
| 8822 | 3534 | true_len = (ulint)cs->cset->well_formed_len( | |
| 8823 | 3534 | cs, (const char *)data, (const char *)data + len, | |
| 8824 |
1/2✓ Branch 0 taken 3534 times.
✗ Branch 1 not taken.
|
3534 | (uint)(key_len / cs->mbmaxlen), &error); |
| 8825 | } | ||
| 8826 | |||
| 8827 | /* In a column prefix index, we may need to truncate | ||
| 8828 | the stored value: */ | ||
| 8829 | |||
| 8830 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3559 times.
|
3559 | if (true_len > key_len) { |
| 8831 | ✗ | true_len = key_len; | |
| 8832 | } | ||
| 8833 | |||
| 8834 | 3559 | memcpy(sorted, data, true_len); | |
| 8835 | 3559 | true_len = | |
| 8836 |
1/2✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
|
3559 | wsrep_innobase_mysql_sort(mysql_type, cs->number, sorted, true_len, |
| 8837 | REC_VERSION_56_MAX_INDEX_COL_LEN); | ||
| 8838 | |||
| 8839 |
1/2✓ Branch 0 taken 3559 times.
✗ Branch 1 not taken.
|
3559 | if (wsrep_protocol_version > 1) { |
| 8840 | /* Note that we always reserve the maximum possible | ||
| 8841 | length of the true VARCHAR in the key value, though | ||
| 8842 | only len first bytes after the 2 length bytes contain | ||
| 8843 | actual data. The rest of the space was reset to zero | ||
| 8844 | in the bzero() call above. */ | ||
| 8845 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3559 times.
|
3559 | if (true_len > buff_space) { |
| 8846 | ✗ | fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd)); | |
| 8847 | ✗ | true_len = buff_space; | |
| 8848 | } | ||
| 8849 | 3559 | memcpy(buff, sorted, true_len); | |
| 8850 | 3559 | buff += true_len; | |
| 8851 | 3559 | buff_space -= true_len; | |
| 8852 | } else { | ||
| 8853 | ✗ | buff += key_len; | |
| 8854 | } | ||
| 8855 |
2/4✓ Branch 0 taken 2792863 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2792863 times.
✗ Branch 3 not taken.
|
2792863 | } else if (mysql_type == MYSQL_TYPE_TINY_BLOB || |
| 8856 |
1/2✓ Branch 0 taken 2792863 times.
✗ Branch 1 not taken.
|
2792863 | mysql_type == MYSQL_TYPE_MEDIUM_BLOB || |
| 8857 |
1/2✓ Branch 0 taken 2792863 times.
✗ Branch 1 not taken.
|
2792863 | mysql_type == MYSQL_TYPE_BLOB || |
| 8858 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2792863 times.
|
2792863 | mysql_type == MYSQL_TYPE_LONG_BLOB || |
| 8859 | /* MYSQL_TYPE_GEOMETRY data is treated | ||
| 8860 | as BLOB data in innodb. */ | ||
| 8861 | mysql_type == MYSQL_TYPE_GEOMETRY) { | ||
| 8862 | const CHARSET_INFO *cs; | ||
| 8863 | ulint key_len; | ||
| 8864 | ulint true_len; | ||
| 8865 | ✗ | int error = 0; | |
| 8866 | ulint blob_len; | ||
| 8867 | const byte *blob_data; | ||
| 8868 | |||
| 8869 | ✗ | ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); | |
| 8870 | |||
| 8871 | ✗ | key_len = key_part->length; | |
| 8872 | |||
| 8873 | ✗ | if (part_is_null) { | |
| 8874 | ✗ | true_len = key_len + 2; | |
| 8875 | ✗ | if (true_len > buff_space) { | |
| 8876 | ✗ | fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd)); | |
| 8877 | ✗ | true_len = buff_space; | |
| 8878 | } | ||
| 8879 | ✗ | buff += true_len; | |
| 8880 | ✗ | buff_space -= true_len; | |
| 8881 | |||
| 8882 | ✗ | continue; | |
| 8883 | } | ||
| 8884 | |||
| 8885 | ✗ | cs = field->charset(); | |
| 8886 | |||
| 8887 | ✗ | blob_data = row_mysql_read_blob_ref( | |
| 8888 | ✗ | &blob_len, (byte *)(record + (ulint)get_field_offset(table, field)), | |
| 8889 | ✗ | (ulint)field->pack_length(), false, 0, 0, &prebuilt->compress_heap); | |
| 8890 | |||
| 8891 | ✗ | true_len = blob_len; | |
| 8892 | |||
| 8893 | ✗ | ut_a(get_field_offset(table, field) == key_part->offset); | |
| 8894 | |||
| 8895 | /* For multi byte character sets we need to calculate | ||
| 8896 | the true length of the key */ | ||
| 8897 | |||
| 8898 | ✗ | if (blob_len > 0 && cs->mbmaxlen > 1) { | |
| 8899 | ✗ | true_len = (ulint)cs->cset->well_formed_len( | |
| 8900 | ✗ | cs, (const char *)blob_data, (const char *)blob_data + blob_len, | |
| 8901 | ✗ | (uint)(key_len / cs->mbmaxlen), &error); | |
| 8902 | } | ||
| 8903 | |||
| 8904 | /* All indexes on BLOB and TEXT are column prefix | ||
| 8905 | indexes, and we may need to truncate the data to be | ||
| 8906 | stored in the key value: */ | ||
| 8907 | |||
| 8908 | ✗ | if (true_len > key_len) { | |
| 8909 | ✗ | true_len = key_len; | |
| 8910 | } | ||
| 8911 | |||
| 8912 | ✗ | memcpy(sorted, blob_data, true_len); | |
| 8913 | ✗ | true_len = | |
| 8914 | ✗ | wsrep_innobase_mysql_sort(mysql_type, cs->number, sorted, true_len, | |
| 8915 | REC_VERSION_56_MAX_INDEX_COL_LEN); | ||
| 8916 | |||
| 8917 | /* Note that we always reserve the maximum possible | ||
| 8918 | length of the BLOB prefix in the key value. */ | ||
| 8919 | ✗ | ut_a(wsrep_protocol_version > 1); | |
| 8920 | ✗ | if (true_len > buff_space) { | |
| 8921 | ✗ | ib::warn() << "WSREP: key truncated: %s " << wsrep_thd_query(thd); | |
| 8922 | ✗ | true_len = buff_space; | |
| 8923 | } | ||
| 8924 | ✗ | memcpy(buff, sorted, true_len); | |
| 8925 | ✗ | buff += true_len; | |
| 8926 | ✗ | buff_space -= true_len; | |
| 8927 | |||
| 8928 | ✗ | } else { | |
| 8929 | /* Here we handle all other data types except the | ||
| 8930 | true VARCHAR, BLOB and TEXT. Note that the column | ||
| 8931 | value we store may be also in a column prefix index. */ | ||
| 8932 | |||
| 8933 | 2792863 | const CHARSET_INFO *cs = NULL; | |
| 8934 | ulint true_len; | ||
| 8935 | ulint key_len; | ||
| 8936 | const uchar *src_start; | ||
| 8937 | 2792863 | int error = 0; | |
| 8938 | enum_field_types real_type; | ||
| 8939 | |||
| 8940 | 2792863 | key_len = key_part->length; | |
| 8941 | |||
| 8942 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2792860 times.
|
2792863 | if (part_is_null) { |
| 8943 | 3 | true_len = key_len; | |
| 8944 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (true_len > buff_space) { |
| 8945 | ✗ | fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd)); | |
| 8946 | ✗ | true_len = buff_space; | |
| 8947 | } | ||
| 8948 | 3 | buff += true_len; | |
| 8949 | 3 | buff_space -= true_len; | |
| 8950 | |||
| 8951 | 3 | continue; | |
| 8952 | } | ||
| 8953 | |||
| 8954 | 2792860 | src_start = record + key_part->offset; | |
| 8955 |
1/2✓ Branch 0 taken 2792860 times.
✗ Branch 1 not taken.
|
2792860 | real_type = field->real_type(); |
| 8956 | 2792860 | true_len = key_len; | |
| 8957 | |||
| 8958 | /* Character set for the field is defined only | ||
| 8959 | to fields whose type is string and real field | ||
| 8960 | type is not enum or set. For these fields check | ||
| 8961 | if character set is multi byte. */ | ||
| 8962 | |||
| 8963 |
4/6✓ Branch 0 taken 2792847 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 2792847 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2792847 times.
✗ Branch 5 not taken.
|
2792860 | if (real_type != MYSQL_TYPE_ENUM && real_type != MYSQL_TYPE_SET && |
| 8964 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2792843 times.
|
2792847 | (mysql_type == MYSQL_TYPE_VAR_STRING || |
| 8965 | mysql_type == MYSQL_TYPE_STRING)) { | ||
| 8966 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | cs = field->charset(); |
| 8967 | |||
| 8968 | /* For multi byte character sets we need to | ||
| 8969 | calculate the true length of the key */ | ||
| 8970 | |||
| 8971 |
3/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
4 | if (key_len > 0 && cs->mbmaxlen > 1) { |
| 8972 | 2 | true_len = (ulint)cs->cset->well_formed_len( | |
| 8973 | cs, (const char *)src_start, (const char *)src_start + key_len, | ||
| 8974 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | (uint)(key_len / cs->mbmaxlen), &error); |
| 8975 | } | ||
| 8976 | 4 | memcpy(sorted, src_start, true_len); | |
| 8977 | 4 | true_len = | |
| 8978 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | wsrep_innobase_mysql_sort(mysql_type, cs->number, sorted, true_len, |
| 8979 | REC_VERSION_56_MAX_INDEX_COL_LEN); | ||
| 8980 | |||
| 8981 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (true_len > buff_space) { |
| 8982 | ✗ | fprintf(stderr, "WSREP: key truncated: %s\n", wsrep_thd_query(thd)); | |
| 8983 | ✗ | true_len = buff_space; | |
| 8984 | } | ||
| 8985 | 4 | memcpy(buff, sorted, true_len); | |
| 8986 | } else { | ||
| 8987 | 2792856 | memcpy(buff, src_start, true_len); | |
| 8988 | } | ||
| 8989 | 2792860 | buff += true_len; | |
| 8990 | 2792860 | buff_space -= true_len; | |
| 8991 | } | ||
| 8992 | } | ||
| 8993 | |||
| 8994 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2796376 times.
|
2796376 | ut_a(buff <= buff_start + buff_len); |
| 8995 | |||
| 8996 |
1/2✓ Branch 0 taken 2796376 times.
✗ Branch 1 not taken.
|
2796376 | DBUG_RETURN((uint)(buff - buff_start)); |
| 8997 | } | ||
| 8998 | #endif /* WITH_WSREP */ | ||
| 8999 | |||
| 9000 | /** Compare two character string according to their charset. | ||
| 9001 | @param[in] cs Character set | ||
| 9002 | @param[in] p1 Key | ||
| 9003 | @param[in] p2 Node */ | ||
| 9004 | 270294085 | extern int innobase_fts_text_cmp(const void *cs, const void *p1, | |
| 9005 | const void *p2) { | ||
| 9006 | 270294085 | const CHARSET_INFO *charset = (const CHARSET_INFO *)cs; | |
| 9007 | 270294085 | const fts_string_t *s1 = (const fts_string_t *)p1; | |
| 9008 | 270294085 | const fts_string_t *s2 = (const fts_string_t *)p2; | |
| 9009 | |||
| 9010 | 540578288 | return (ha_compare_text(charset, s1->f_str, static_cast<uint>(s1->f_len), | |
| 9011 | 270294085 | s2->f_str, static_cast<uint>(s2->f_len), false)); | |
| 9012 | } | ||
| 9013 | |||
| 9014 | /** Compare two FTS character strings case insensitively according to their | ||
| 9015 | charset. This assumes that s1 is already in lower case. | ||
| 9016 | @param[in] cs character set | ||
| 9017 | @param[in] s1 key | ||
| 9018 | @param[in] s2 node | ||
| 9019 | @return 0 if the two strings are equal */ | ||
| 9020 | 1072 | int innobase_fts_nocase_compare(const CHARSET_INFO *cs, const fts_string_t *s1, | |
| 9021 | const fts_string_t *s2) { | ||
| 9022 | ulint newlen; | ||
| 9023 | |||
| 9024 |
2/2✓ Branch 0 taken 1029 times.
✓ Branch 1 taken 43 times.
|
1072 | if (!my_binary_compare(cs)) { |
| 9025 | 1029 | my_casedn_str(cs, (char *)s2->f_str); | |
| 9026 | } | ||
| 9027 | |||
| 9028 | 1072 | newlen = strlen((const char *)s2->f_str); | |
| 9029 | |||
| 9030 | 2144 | return (ha_compare_text(cs, s1->f_str, static_cast<uint>(s1->f_len), | |
| 9031 | 1072 | s2->f_str, static_cast<uint>(newlen), false)); | |
| 9032 | } | ||
| 9033 | |||
| 9034 | #endif /* UNIV_HOTBACKUP */ | ||
| 9035 | |||
| 9036 | /** Compare two character strings case insensitively according to their | ||
| 9037 | charset. | ||
| 9038 | @param[in] cs character set | ||
| 9039 | @param[in] s1 string 1 | ||
| 9040 | @param[in] s2 string 2 | ||
| 9041 | @return 0 if the two strings are equal */ | ||
| 9042 | ✗ | int innobase_nocase_compare(const void *cs, const char *s1, const char *s2) { | |
| 9043 | ✗ | const CHARSET_INFO *charset = static_cast<const CHARSET_INFO *>(cs); | |
| 9044 | ✗ | const uchar *str1 = reinterpret_cast<const uchar *>(s1); | |
| 9045 | ✗ | const uchar *str2 = reinterpret_cast<const uchar *>(s2); | |
| 9046 | ✗ | uint len1 = static_cast<uint>(strlen(s1)); | |
| 9047 | ✗ | uint len2 = static_cast<uint>(strlen(s2)); | |
| 9048 | |||
| 9049 | /* This function returns zero if the two strings are equal. */ | ||
| 9050 | ✗ | return (ha_compare_text(charset, str1, len1, str2, len2, false)); | |
| 9051 | } | ||
| 9052 | |||
| 9053 | #ifndef UNIV_HOTBACKUP | ||
| 9054 | |||
| 9055 | 2492017 | ulint innobase_strnxfrm(const CHARSET_INFO *cs, const uchar *str, | |
| 9056 | const ulint len) { | ||
| 9057 | uchar mystr[2]; | ||
| 9058 | ulint value; | ||
| 9059 | |||
| 9060 |
3/4✓ Branch 0 taken 2492051 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2492049 times.
|
2492017 | if (!str || len == 0) { |
| 9061 | ✗ | return (0); | |
| 9062 | } | ||
| 9063 | |||
| 9064 |
1/2✓ Branch 0 taken 2491819 times.
✗ Branch 1 not taken.
|
2492049 | my_strnxfrm(cs, (uchar *)mystr, 2, str, len); |
| 9065 | |||
| 9066 | 2491819 | value = mach_read_from_2(mystr); | |
| 9067 | |||
| 9068 |
2/2✓ Branch 0 taken 2483704 times.
✓ Branch 1 taken 8072 times.
|
2491776 | if (value > 255) { |
| 9069 | 2483704 | value = value / 256; | |
| 9070 | } | ||
| 9071 | |||
| 9072 | 2491776 | return (value); | |
| 9073 | } | ||
| 9074 | |||
| 9075 | /** Compare two character string according to their charset. | ||
| 9076 | @param[in] cs Character set | ||
| 9077 | @param[in] p1 Key | ||
| 9078 | @param[in] p2 Node */ | ||
| 9079 | 549 | extern int innobase_fts_text_cmp_prefix(const void *cs, const void *p1, | |
| 9080 | const void *p2) { | ||
| 9081 | 549 | const CHARSET_INFO *charset = (const CHARSET_INFO *)cs; | |
| 9082 | 549 | const fts_string_t *s1 = (const fts_string_t *)p1; | |
| 9083 | 549 | const fts_string_t *s2 = (const fts_string_t *)p2; | |
| 9084 | int result; | ||
| 9085 | |||
| 9086 | 1098 | result = ha_compare_text(charset, s2->f_str, static_cast<uint>(s2->f_len), | |
| 9087 | 549 | s1->f_str, static_cast<uint>(s1->f_len), true); | |
| 9088 | |||
| 9089 | /* We switched s1, s2 position in ha_compare_text. So we need | ||
| 9090 | to negate the result */ | ||
| 9091 | 549 | return (-result); | |
| 9092 | } | ||
| 9093 | |||
| 9094 | /** Makes all characters in a string lower case. | ||
| 9095 | @param[in] cs Character set | ||
| 9096 | @param[in] src String to put in lower case | ||
| 9097 | @param[in] src_len Input string length | ||
| 9098 | @param[in] dst Buffer for result string | ||
| 9099 | @param[in] dst_len Buffer size */ | ||
| 9100 | 1478154 | extern size_t innobase_fts_casedn_str(CHARSET_INFO *cs, char *src, | |
| 9101 | size_t src_len, char *dst, | ||
| 9102 | size_t dst_len) { | ||
| 9103 |
2/2✓ Branch 0 taken 1476672 times.
✓ Branch 1 taken 1482 times.
|
1478154 | if (cs->casedn_multiply == 1) { |
| 9104 | 1476672 | memcpy(dst, src, src_len); | |
| 9105 | 1476672 | dst[src_len] = 0; | |
| 9106 | 1476672 | my_casedn_str(cs, dst); | |
| 9107 | |||
| 9108 | 1476858 | return (strlen(dst)); | |
| 9109 | } else { | ||
| 9110 | 1482 | return (cs->cset->casedn(cs, src, src_len, dst, dst_len)); | |
| 9111 | } | ||
| 9112 | } | ||
| 9113 | |||
| 9114 | /** Get the next token from the given string and store it in *token. | ||
| 9115 | It is mostly copied from MyISAM's doc parsing function ft_simple_get_word() | ||
| 9116 | @return length of string processed */ | ||
| 9117 | 1566848 | ulint innobase_mysql_fts_get_token( | |
| 9118 | CHARSET_INFO *cs, /*!< in: Character set */ | ||
| 9119 | const byte *start, /*!< in: start of text */ | ||
| 9120 | const byte *end, /*!< in: one character past end of | ||
| 9121 | text */ | ||
| 9122 | bool extra_word_chars, /*!< in: whether consider all non-whitespace | ||
| 9123 | characters to be word characters */ | ||
| 9124 | fts_string_t *token) /*!< out: token's text */ | ||
| 9125 | { | ||
| 9126 | int mbl; | ||
| 9127 | 1566848 | const uchar *doc = start; | |
| 9128 | |||
| 9129 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1566760 times.
|
1566848 | ut_a(cs); |
| 9130 | |||
| 9131 | 1566760 | token->f_n_char = token->f_len = 0; | |
| 9132 | 1566760 | token->f_str = nullptr; | |
| 9133 | |||
| 9134 | for (;;) { | ||
| 9135 |
2/2✓ Branch 0 taken 10173 times.
✓ Branch 1 taken 7510488 times.
|
7520661 | if (doc >= end) { |
| 9136 | 10173 | return (doc - start); | |
| 9137 | } | ||
| 9138 | |||
| 9139 | int ctype; | ||
| 9140 | |||
| 9141 |
1/2✓ Branch 0 taken 7511653 times.
✗ Branch 1 not taken.
|
7510488 | mbl = cs->cset->ctype(cs, &ctype, doc, (const uchar *)end); |
| 9142 | |||
| 9143 |
2/2✓ Branch 0 taken 1557737 times.
✓ Branch 1 taken 5953901 times.
|
7511653 | if (true_word_char(ctype, extra_word_chars, *doc)) { |
| 9144 | 1557737 | break; | |
| 9145 | } | ||
| 9146 | |||
| 9147 |
2/4✓ Branch 0 taken 5955352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
5953901 | doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1); |
| 9148 | 5953901 | } | |
| 9149 | |||
| 9150 | 1557737 | ulint length = 0; | |
| 9151 | |||
| 9152 | 1557737 | token->f_str = const_cast<byte *>(doc); | |
| 9153 | |||
| 9154 |
2/2✓ Branch 0 taken 26553072 times.
✓ Branch 1 taken 663756 times.
|
27216828 | while (doc < end) { |
| 9155 | int ctype; | ||
| 9156 | |||
| 9157 |
1/2✓ Branch 0 taken 26552418 times.
✗ Branch 1 not taken.
|
26553072 | mbl = cs->cset->ctype(cs, &ctype, (uchar *)doc, (uchar *)end); |
| 9158 |
2/2✓ Branch 0 taken 894479 times.
✓ Branch 1 taken 25659091 times.
|
26552418 | if (!true_word_char(ctype, extra_word_chars, *doc)) { |
| 9159 | 894479 | break; | |
| 9160 | } | ||
| 9161 | |||
| 9162 | 25659091 | ++length; | |
| 9163 | |||
| 9164 |
1/4✓ Branch 0 taken 25662145 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
25659091 | doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1); |
| 9165 | } | ||
| 9166 | |||
| 9167 | 1558235 | token->f_len = (uint)(doc - token->f_str); | |
| 9168 | 1558235 | token->f_n_char = length; | |
| 9169 | |||
| 9170 | 1558235 | return (doc - start); | |
| 9171 | } | ||
| 9172 | |||
| 9173 | /** Converts a MySQL type to an InnoDB type. Note that this function returns | ||
| 9174 | the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1 | ||
| 9175 | VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'. | ||
| 9176 | @param[out] unsigned_flag DATA_UNSIGNED if an 'unsigned type'; at least | ||
| 9177 | ENUM and SET, and unsigned integer types are 'unsigned types' | ||
| 9178 | @param[in] f MySQL Field | ||
| 9179 | @return DATA_BINARY, DATA_VARCHAR, ... */ | ||
| 9180 | 21488816 | ulint get_innobase_type_from_mysql_type(ulint *unsigned_flag, const void *f) { | |
| 9181 | 21488816 | const class Field *field = reinterpret_cast<const class Field *>(f); | |
| 9182 | |||
| 9183 | /* The following asserts try to check that the MySQL type code fits in | ||
| 9184 | 8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to | ||
| 9185 | the type */ | ||
| 9186 | |||
| 9187 | assert((ulint)MYSQL_TYPE_STRING < 256); | ||
| 9188 | assert((ulint)MYSQL_TYPE_VAR_STRING < 256); | ||
| 9189 | assert((ulint)MYSQL_TYPE_DOUBLE < 256); | ||
| 9190 | assert((ulint)MYSQL_TYPE_FLOAT < 256); | ||
| 9191 | assert((ulint)MYSQL_TYPE_DECIMAL < 256); | ||
| 9192 | |||
| 9193 |
2/2✓ Branch 0 taken 6962320 times.
✓ Branch 1 taken 14526499 times.
|
21488816 | if (field->is_flag_set(UNSIGNED_FLAG)) { |
| 9194 | 6962320 | *unsigned_flag = DATA_UNSIGNED; | |
| 9195 | } else { | ||
| 9196 | 14526499 | *unsigned_flag = 0; | |
| 9197 | } | ||
| 9198 | |||
| 9199 |
4/4✓ Branch 0 taken 19971480 times.
✓ Branch 1 taken 1517339 times.
✓ Branch 2 taken 1604934 times.
✓ Branch 3 taken 19883884 times.
|
41460298 | if (field->real_type() == MYSQL_TYPE_ENUM || |
| 9200 |
2/2✓ Branch 0 taken 87595 times.
✓ Branch 1 taken 19883884 times.
|
19971480 | field->real_type() == MYSQL_TYPE_SET) { |
| 9201 | /* MySQL has field->type() a string type for these, but the | ||
| 9202 | data is actually internally stored as an unsigned integer | ||
| 9203 | code! */ | ||
| 9204 | |||
| 9205 | 1604934 | *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned | |
| 9206 | flag set to zero, even though | ||
| 9207 | internally this is an unsigned | ||
| 9208 | integer type */ | ||
| 9209 | 1604934 | return (DATA_INT); | |
| 9210 | } | ||
| 9211 | |||
| 9212 |
9/12✓ Branch 0 taken 6088453 times.
✓ Branch 1 taken 1943406 times.
✓ Branch 2 taken 20810 times.
✓ Branch 3 taken 9665340 times.
✓ Branch 4 taken 495708 times.
✓ Branch 5 taken 61879 times.
✓ Branch 6 taken 29321 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3926 times.
✓ Branch 9 taken 1575042 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
19883884 | switch (field->type()) { |
| 9213 | /* NOTE that we only allow string types in DATA_MYSQL and | ||
| 9214 | DATA_VARMYSQL */ | ||
| 9215 | 6088453 | case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */ | |
| 9216 | case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */ | ||
| 9217 |
2/2✓ Branch 0 taken 41170 times.
✓ Branch 1 taken 6047283 times.
|
6088453 | if (field->binary()) { |
| 9218 | 41170 | return (DATA_BINARY); | |
| 9219 |
2/2✓ Branch 0 taken 71109 times.
✓ Branch 1 taken 5976174 times.
|
6047283 | } else if (field->charset() == &my_charset_latin1) { |
| 9220 | 71109 | return (DATA_VARCHAR); | |
| 9221 | } else { | ||
| 9222 | 5976174 | return (DATA_VARMYSQL); | |
| 9223 | } | ||
| 9224 | 1943406 | case MYSQL_TYPE_BIT: | |
| 9225 | case MYSQL_TYPE_STRING: | ||
| 9226 |
2/2✓ Branch 0 taken 15662 times.
✓ Branch 1 taken 1927744 times.
|
1943406 | if (field->binary()) { |
| 9227 | 15662 | return (DATA_FIXBINARY); | |
| 9228 |
2/2✓ Branch 0 taken 11123 times.
✓ Branch 1 taken 1916621 times.
|
1927744 | } else if (field->charset() == &my_charset_latin1) { |
| 9229 | 11123 | return (DATA_CHAR); | |
| 9230 | } else { | ||
| 9231 | 1916621 | return (DATA_MYSQL); | |
| 9232 | } | ||
| 9233 | 20810 | case MYSQL_TYPE_NEWDECIMAL: | |
| 9234 | 20810 | return (DATA_FIXBINARY); | |
| 9235 | 9665340 | case MYSQL_TYPE_LONG: | |
| 9236 | case MYSQL_TYPE_LONGLONG: | ||
| 9237 | case MYSQL_TYPE_TINY: | ||
| 9238 | case MYSQL_TYPE_SHORT: | ||
| 9239 | case MYSQL_TYPE_INT24: | ||
| 9240 | case MYSQL_TYPE_DATE: | ||
| 9241 | case MYSQL_TYPE_YEAR: | ||
| 9242 | case MYSQL_TYPE_NEWDATE: | ||
| 9243 | case MYSQL_TYPE_BOOL: | ||
| 9244 | 9665340 | return (DATA_INT); | |
| 9245 | 495708 | case MYSQL_TYPE_TIME: | |
| 9246 | case MYSQL_TYPE_DATETIME: | ||
| 9247 | case MYSQL_TYPE_TIMESTAMP: | ||
| 9248 | case MYSQL_TYPE_TIME2: | ||
| 9249 | case MYSQL_TYPE_DATETIME2: | ||
| 9250 | case MYSQL_TYPE_TIMESTAMP2: | ||
| 9251 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 495708 times.
|
495708 | switch (field->real_type()) { |
| 9252 | ✗ | case MYSQL_TYPE_TIME: | |
| 9253 | case MYSQL_TYPE_DATETIME: | ||
| 9254 | case MYSQL_TYPE_TIMESTAMP: | ||
| 9255 | ✗ | return (DATA_INT); | |
| 9256 | 495708 | default: | |
| 9257 | assert((ulint)MYSQL_TYPE_DECIMAL < 256); | ||
| 9258 | [[fallthrough]]; | ||
| 9259 | case MYSQL_TYPE_TIME2: | ||
| 9260 | case MYSQL_TYPE_DATETIME2: | ||
| 9261 | case MYSQL_TYPE_TIMESTAMP2: | ||
| 9262 | 495708 | return (DATA_FIXBINARY); | |
| 9263 | } | ||
| 9264 | 61879 | case MYSQL_TYPE_FLOAT: | |
| 9265 | 61879 | return (DATA_FLOAT); | |
| 9266 | 29321 | case MYSQL_TYPE_DOUBLE: | |
| 9267 | 29321 | return (DATA_DOUBLE); | |
| 9268 | ✗ | case MYSQL_TYPE_DECIMAL: | |
| 9269 | ✗ | return (DATA_DECIMAL); | |
| 9270 | 3926 | case MYSQL_TYPE_GEOMETRY: | |
| 9271 | 3926 | return (DATA_GEOMETRY); | |
| 9272 | 1575042 | case MYSQL_TYPE_TINY_BLOB: | |
| 9273 | case MYSQL_TYPE_MEDIUM_BLOB: | ||
| 9274 | case MYSQL_TYPE_BLOB: | ||
| 9275 | case MYSQL_TYPE_LONG_BLOB: | ||
| 9276 | case MYSQL_TYPE_JSON: // JSON fields are stored as BLOBs | ||
| 9277 | 1575042 | return (DATA_BLOB); | |
| 9278 | ✗ | case MYSQL_TYPE_NULL: | |
| 9279 | /* MySQL currently accepts "NULL" datatype, but will | ||
| 9280 | reject such datatype in the next release. We will cope | ||
| 9281 | with it and not trigger assertion failure in 5.1 */ | ||
| 9282 | ✗ | break; | |
| 9283 | ✗ | default: | |
| 9284 | ✗ | ut_error; | |
| 9285 | } | ||
| 9286 | |||
| 9287 | ✗ | return (0); | |
| 9288 | } | ||
| 9289 | |||
| 9290 | /** Converts a MySQL data-dictionary type to an InnoDB type. Also returns | ||
| 9291 | a few attributes which are useful for precise type calculation. | ||
| 9292 | |||
| 9293 | @note This function is version of get_innobase_type_from_mysql_type() with | ||
| 9294 | added knowledge about how additional attributes calculated (e.g. in | ||
| 9295 | create_table_info_t::create_table_def()) and about behavior of Field | ||
| 9296 | class and its descendats. | ||
| 9297 | |||
| 9298 | @note It allows to get InnoDB generic and precise types directly from MySQL | ||
| 9299 | data-dictionary info, bypassing expensive construction of Field objects. | ||
| 9300 | |||
| 9301 | @param[out] unsigned_flag DATA_UNSIGNED if an 'unsigned type'. | ||
| 9302 | @param[out] binary_type DATA_BINARY_TYPE if a 'binary type'. | ||
| 9303 | @param[out] charset_no Collation id for string types. | ||
| 9304 | @param[in] dd_type MySQL data-dictionary type. | ||
| 9305 | @param[in] field_charset Charset. | ||
| 9306 | @param[in] is_unsigned MySQL data-dictionary unsigned flag. | ||
| 9307 | |||
| 9308 | @return DATA_BINARY, DATA_VARCHAR, ... */ | ||
| 9309 | 557911 | ulint get_innobase_type_from_mysql_dd_type(ulint *unsigned_flag, | |
| 9310 | ulint *binary_type, | ||
| 9311 | ulint *charset_no, | ||
| 9312 | dd::enum_column_types dd_type, | ||
| 9313 | const CHARSET_INFO *field_charset, | ||
| 9314 | bool is_unsigned) { | ||
| 9315 | /* InnoDB's unsigned flag is based on UNSIGNED_FLAG bit in Field::flags. | ||
| 9316 | This bit is unset for Field objects by default. */ | ||
| 9317 | 557911 | *unsigned_flag = 0; | |
| 9318 | /* InnoDB's binary type flag is based on result of Field::binary() call. | ||
| 9319 | The latter returns true by default. */ | ||
| 9320 | 557911 | *binary_type = DATA_BINARY_TYPE; | |
| 9321 | /* InnoDB takes into account charset numbers only for columns which it | ||
| 9322 | considers of string type. */ | ||
| 9323 | 557911 | *charset_no = 0; | |
| 9324 | |||
| 9325 |
9/13✓ Branch 0 taken 38 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 766 times.
✓ Branch 4 taken 556877 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
557911 | switch (dd_type) { |
| 9326 | 38 | case dd::enum_column_types::ENUM: | |
| 9327 | case dd::enum_column_types::SET: | ||
| 9328 | /* SQL-layer has its own unsigned flag set to zero, even though | ||
| 9329 | internally this is an unsigned integer type. */ | ||
| 9330 | 38 | *unsigned_flag = DATA_UNSIGNED; | |
| 9331 | /* ENUM and SET are handled as string types by SQL-layer, | ||
| 9332 | hence the charset check. */ | ||
| 9333 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 2 times.
|
38 | if (field_charset != &my_charset_bin) *binary_type = 0; |
| 9334 | 38 | return (DATA_INT); | |
| 9335 | 175 | case dd::enum_column_types::VAR_STRING: /* old <= 4.1 VARCHAR. */ | |
| 9336 | case dd::enum_column_types::VARCHAR: /* new >= 5.0.3 true VARCHAR. */ | ||
| 9337 | 175 | *charset_no = field_charset->number; | |
| 9338 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 162 times.
|
175 | if (field_charset == &my_charset_bin) { |
| 9339 | 13 | return (DATA_BINARY); | |
| 9340 | } else { | ||
| 9341 | 162 | *binary_type = 0; | |
| 9342 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 122 times.
|
162 | if (field_charset == &my_charset_latin1) { |
| 9343 | 40 | return (DATA_VARCHAR); | |
| 9344 | } else { | ||
| 9345 | 122 | return (DATA_VARMYSQL); | |
| 9346 | } | ||
| 9347 | } | ||
| 9348 | 15 | case dd::enum_column_types::BIT: | |
| 9349 | /* MySQL always sets unsigned flag for both its BIT types. */ | ||
| 9350 | 15 | *unsigned_flag = DATA_UNSIGNED; | |
| 9351 | 15 | *charset_no = my_charset_bin.number; | |
| 9352 | 15 | return (DATA_FIXBINARY); | |
| 9353 | 766 | case dd::enum_column_types::STRING: | |
| 9354 | 766 | *charset_no = field_charset->number; | |
| 9355 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 713 times.
|
766 | if (field_charset == &my_charset_bin) { |
| 9356 | 53 | return (DATA_FIXBINARY); | |
| 9357 | } else { | ||
| 9358 | 713 | *binary_type = 0; | |
| 9359 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 701 times.
|
713 | if (field_charset == &my_charset_latin1) { |
| 9360 | 12 | return (DATA_CHAR); | |
| 9361 | } else { | ||
| 9362 | 701 | return (DATA_MYSQL); | |
| 9363 | } | ||
| 9364 | } | ||
| 9365 | 556877 | case dd::enum_column_types::DECIMAL: | |
| 9366 | case dd::enum_column_types::FLOAT: | ||
| 9367 | case dd::enum_column_types::DOUBLE: | ||
| 9368 | case dd::enum_column_types::NEWDECIMAL: | ||
| 9369 | case dd::enum_column_types::LONG: | ||
| 9370 | case dd::enum_column_types::LONGLONG: | ||
| 9371 | case dd::enum_column_types::TINY: | ||
| 9372 | case dd::enum_column_types::SHORT: | ||
| 9373 | case dd::enum_column_types::INT24: | ||
| 9374 | /* Types based on Field_num set unsigned flag from value stored | ||
| 9375 | in the data-dictionary (YEAR being the exception). */ | ||
| 9376 |
2/2✓ Branch 0 taken 546088 times.
✓ Branch 1 taken 10789 times.
|
556877 | if (is_unsigned) *unsigned_flag = DATA_UNSIGNED; |
| 9377 | switch (dd_type) { | ||
| 9378 | ✗ | case dd::enum_column_types::DECIMAL: | |
| 9379 | ✗ | return (DATA_DECIMAL); | |
| 9380 | 17 | case dd::enum_column_types::FLOAT: | |
| 9381 | 17 | return (DATA_FLOAT); | |
| 9382 | 5 | case dd::enum_column_types::DOUBLE: | |
| 9383 | 5 | return (DATA_DOUBLE); | |
| 9384 | 14 | case dd::enum_column_types::NEWDECIMAL: | |
| 9385 | 14 | *charset_no = my_charset_bin.number; | |
| 9386 | 14 | return (DATA_FIXBINARY); | |
| 9387 | 556841 | default: | |
| 9388 | 556841 | break; | |
| 9389 | } | ||
| 9390 | 556841 | return (DATA_INT); | |
| 9391 | 14 | case dd::enum_column_types::DATE: | |
| 9392 | case dd::enum_column_types::NEWDATE: | ||
| 9393 | case dd::enum_column_types::TIME: | ||
| 9394 | case dd::enum_column_types::DATETIME: | ||
| 9395 | 14 | return (DATA_INT); | |
| 9396 | 3 | case dd::enum_column_types::YEAR: | |
| 9397 | case dd::enum_column_types::TIMESTAMP: | ||
| 9398 | /* MySQL always sets unsigned flag for YEAR and old TIMESTAMP type. */ | ||
| 9399 | 3 | *unsigned_flag = DATA_UNSIGNED; | |
| 9400 | 3 | return (DATA_INT); | |
| 9401 | 20 | case dd::enum_column_types::TIME2: | |
| 9402 | case dd::enum_column_types::DATETIME2: | ||
| 9403 | case dd::enum_column_types::TIMESTAMP2: | ||
| 9404 | 20 | *charset_no = my_charset_bin.number; | |
| 9405 | 20 | return (DATA_FIXBINARY); | |
| 9406 | ✗ | case dd::enum_column_types::GEOMETRY: | |
| 9407 | /* Field_geom::binary() is always true. */ | ||
| 9408 | ✗ | return (DATA_GEOMETRY); | |
| 9409 | 3 | case dd::enum_column_types::TINY_BLOB: | |
| 9410 | case dd::enum_column_types::MEDIUM_BLOB: | ||
| 9411 | case dd::enum_column_types::BLOB: | ||
| 9412 | case dd::enum_column_types::LONG_BLOB: | ||
| 9413 | 3 | *charset_no = field_charset->number; | |
| 9414 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (field_charset != &my_charset_bin) *binary_type = 0; |
| 9415 | 3 | return (DATA_BLOB); | |
| 9416 | ✗ | case dd::enum_column_types::JSON: | |
| 9417 | /* JSON fields are stored as BLOBs. | ||
| 9418 | Field_json::binary() always returns true even though data in | ||
| 9419 | such columns are stored in UTF8. */ | ||
| 9420 | ✗ | *charset_no = my_charset_utf8mb4_bin.number; | |
| 9421 | ✗ | return (DATA_BLOB); | |
| 9422 | ✗ | case dd::enum_column_types::TYPE_NULL: | |
| 9423 | /* Compatibility with get_innobase_type_from_mysql_type(). */ | ||
| 9424 | ✗ | *charset_no = field_charset->number; | |
| 9425 | ✗ | if (field_charset != &my_charset_bin) *binary_type = 0; | |
| 9426 | ✗ | break; | |
| 9427 | ✗ | default: | |
| 9428 | ✗ | ut_error; | |
| 9429 | } | ||
| 9430 | |||
| 9431 | ✗ | return (0); | |
| 9432 | } | ||
| 9433 | |||
| 9434 | /** Reads an unsigned integer value < 64k from 2 bytes, in the little-endian | ||
| 9435 | storage format. | ||
| 9436 | @return value */ | ||
| 9437 | 86 | static inline uint innobase_read_from_2_little_endian( | |
| 9438 | const uchar *buf) /*!< in: from where to read */ | ||
| 9439 | { | ||
| 9440 | 86 | return ((uint)((ulint)(buf[0]) + 256 * ((ulint)(buf[1])))); | |
| 9441 | } | ||
| 9442 | |||
| 9443 | /** Determines if a field is needed in a m_prebuilt struct 'template'. | ||
| 9444 | @return field to use, or NULL if the field is not needed */ | ||
| 9445 | 1541892974 | static const Field *build_template_needs_field( | |
| 9446 | bool index_contains, /*!< in: | ||
| 9447 | dict_index_contains_col_or_prefix( | ||
| 9448 | index, i) */ | ||
| 9449 | bool read_just_key, /*!< in: true when MySQL calls | ||
| 9450 | ha_innobase::extra with the | ||
| 9451 | argument HA_EXTRA_KEYREAD; it is enough | ||
| 9452 | to read just columns defined in | ||
| 9453 | the index (i.e., no read of the | ||
| 9454 | clustered index record necessary) */ | ||
| 9455 | bool fetch_all_in_key, | ||
| 9456 | /*!< in: true=fetch all fields in | ||
| 9457 | the index */ | ||
| 9458 | bool fetch_primary_key_cols, | ||
| 9459 | /*!< in: true=fetch the | ||
| 9460 | primary key columns */ | ||
| 9461 | dict_index_t *index, /*!< in: InnoDB index to use */ | ||
| 9462 | const TABLE *table, /*!< in: MySQL table object */ | ||
| 9463 | ulint i, /*!< in: field index in InnoDB table */ | ||
| 9464 | ulint num_v) /*!< in: num virtual column so far */ | ||
| 9465 | { | ||
| 9466 | 1541892974 | const Field *field = table->field[i]; | |
| 9467 | |||
| 9468 |
2/2✓ Branch 0 taken 876323598 times.
✓ Branch 1 taken 665569376 times.
|
1541892974 | if (!index_contains) { |
| 9469 |
2/2✓ Branch 0 taken 5650562 times.
✓ Branch 1 taken 870673036 times.
|
876323598 | if (read_just_key) { |
| 9470 | /* If this is a 'key read', we do not need | ||
| 9471 | columns that are not in the key */ | ||
| 9472 | |||
| 9473 | 5650562 | return (nullptr); | |
| 9474 | } | ||
| 9475 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 665569376 times.
|
665569376 | } else if (fetch_all_in_key) { |
| 9476 | /* This field is needed in the query */ | ||
| 9477 | |||
| 9478 | ✗ | return (field); | |
| 9479 | } | ||
| 9480 | |||
| 9481 |
6/6✓ Branch 0 taken 53893996 times.
✓ Branch 1 taken 1482350376 times.
✓ Branch 2 taken 516012 times.
✓ Branch 3 taken 53379132 times.
✓ Branch 4 taken 1482866432 times.
✓ Branch 5 taken 53379088 times.
|
1590137556 | if (bitmap_is_set(table->read_set, static_cast<uint>(i)) || |
| 9482 | 53893996 | bitmap_is_set(table->write_set, static_cast<uint>(i))) { | |
| 9483 | /* This field is needed in the query */ | ||
| 9484 | |||
| 9485 | 1482866432 | return (field); | |
| 9486 | } | ||
| 9487 | |||
| 9488 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53379095 times.
|
53379088 | ut_ad(i >= num_v); |
| 9489 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 53379095 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 53379095 times.
|
53379095 | if (fetch_primary_key_cols && |
| 9490 | ✗ | dict_table_col_in_clustered_key(index->table, i - num_v)) { | |
| 9491 | /* This field is needed in the query */ | ||
| 9492 | |||
| 9493 | ✗ | return (field); | |
| 9494 | } | ||
| 9495 | |||
| 9496 | /* This field is not needed in the query, skip it */ | ||
| 9497 | |||
| 9498 | 53379095 | return (nullptr); | |
| 9499 | } | ||
| 9500 | |||
| 9501 | /** Determines if a field is needed in a m_prebuilt struct 'template'. | ||
| 9502 | @return whether the field is needed for index condition pushdown */ | ||
| 9503 | 49930 | inline bool build_template_needs_field_in_icp( | |
| 9504 | const dict_index_t *index, /*!< in: InnoDB index */ | ||
| 9505 | const row_prebuilt_t *prebuilt, /*!< in: row fetch template */ | ||
| 9506 | bool contains, /*!< in: whether the index contains | ||
| 9507 | column i */ | ||
| 9508 | ulint i, /*!< in: column number */ | ||
| 9509 | bool is_virtual) | ||
| 9510 | /*!< in: a virtual column or not */ | ||
| 9511 | { | ||
| 9512 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49930 times.
|
49930 | ut_ad(contains == dict_index_contains_col_or_prefix(index, i, is_virtual)); |
| 9513 | |||
| 9514 |
2/2✓ Branch 0 taken 49522 times.
✓ Branch 1 taken 408 times.
|
49930 | return (index == prebuilt->index ? contains |
| 9515 | 408 | : dict_index_contains_col_or_prefix( | |
| 9516 | 50338 | prebuilt->index, i, is_virtual)); | |
| 9517 | } | ||
| 9518 | |||
| 9519 | /** Adds a field to a m_prebuilt struct 'template'. | ||
| 9520 | @return the field template */ | ||
| 9521 | 2005649955 | static mysql_row_templ_t *build_template_field( | |
| 9522 | row_prebuilt_t *prebuilt, /*!< in/out: template */ | ||
| 9523 | dict_index_t *clust_index, /*!< in: InnoDB clustered index */ | ||
| 9524 | dict_index_t *index, /*!< in: InnoDB index to use */ | ||
| 9525 | TABLE *table, /*!< in: MySQL table object */ | ||
| 9526 | const Field *field, /*!< in: field in MySQL table */ | ||
| 9527 | ulint i, /*!< in: field index in InnoDB table */ | ||
| 9528 | ulint v_no) /*!< in: field index for virtual col */ | ||
| 9529 | { | ||
| 9530 | mysql_row_templ_t *templ; | ||
| 9531 | const dict_col_t *col; | ||
| 9532 | |||
| 9533 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2005649789 times.
|
2005649955 | ut_ad(clust_index->table == index->table); |
| 9534 | |||
| 9535 | 2005649789 | templ = prebuilt->mysql_template + prebuilt->n_template++; | |
| 9536 | UNIV_MEM_INVALID(templ, sizeof *templ); | ||
| 9537 | |||
| 9538 |
4/4✓ Branch 0 taken 257477 times.
✓ Branch 1 taken 2005392312 times.
✓ Branch 2 taken 236632 times.
✓ Branch 3 taken 20845 times.
|
2005649789 | if (innobase_is_v_fld(field)) { |
| 9539 | 236632 | templ->is_virtual = true; | |
| 9540 | 236632 | col = &dict_table_get_nth_v_col(index->table, v_no)->m_col; | |
| 9541 | } else { | ||
| 9542 | 2005413157 | templ->is_virtual = false; | |
| 9543 | 2005413157 | col = index->table->get_col(i); | |
| 9544 | } | ||
| 9545 | |||
| 9546 |
2/2✓ Branch 0 taken 2005411974 times.
✓ Branch 1 taken 236582 times.
|
2005648556 | if (!templ->is_virtual) { |
| 9547 | 2005411974 | templ->col_no = i; | |
| 9548 | 2005411974 | templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index); | |
| 9549 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2005419285 times.
|
2005420317 | ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED); |
| 9550 | 2005419285 | templ->rec_prefix_field_no = ULINT_UNDEFINED; | |
| 9551 | |||
| 9552 |
2/2✓ Branch 0 taken 938467652 times.
✓ Branch 1 taken 1066950100 times.
|
2005419285 | if (index->is_clustered()) { |
| 9553 | 938467652 | templ->rec_field_is_prefix = false; | |
| 9554 | 938467652 | templ->rec_field_no = templ->clust_rec_field_no; | |
| 9555 | } else { | ||
| 9556 | /* If we're in a secondary index, keep track of the original index | ||
| 9557 | position even if this is just a prefix non-geometry index; we will use | ||
| 9558 | this later to avoid a cluster index lookup in some cases. */ | ||
| 9559 | |||
| 9560 | 1066950478 | templ->rec_field_no = index->get_col_pos( | |
| 9561 | i, false, false, | ||
| 9562 |
2/2✓ Branch 0 taken 1066950163 times.
✓ Branch 1 taken 315 times.
|
1066950100 | (field->type() == MYSQL_TYPE_GEOMETRY) ? nullptr |
| 9563 | : &templ->rec_prefix_field_no); | ||
| 9564 | 1066947989 | templ->rec_field_is_prefix = | |
| 9565 |
2/2✓ Branch 0 taken 853158613 times.
✓ Branch 1 taken 213789376 times.
|
1920106602 | (templ->rec_field_no == ULINT_UNDEFINED) && |
| 9566 |
2/2✓ Branch 0 taken 1886 times.
✓ Branch 1 taken 853156727 times.
|
853158613 | (templ->rec_prefix_field_no != ULINT_UNDEFINED); |
| 9567 | #ifdef UNIV_DEBUG | ||
| 9568 |
2/2✓ Branch 0 taken 213792039 times.
✓ Branch 1 taken 853155950 times.
|
1066947989 | if (templ->rec_prefix_field_no != ULINT_UNDEFINED) { |
| 9569 | 213792039 | const auto *const field = index->get_field(templ->rec_prefix_field_no); | |
| 9570 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 213791962 times.
|
213791979 | ut_ad(templ->rec_field_is_prefix == (field->prefix_len != 0)); |
| 9571 | } else { | ||
| 9572 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 853157403 times.
|
853155950 | ut_ad(!templ->rec_field_is_prefix); |
| 9573 | } | ||
| 9574 | #endif | ||
| 9575 | } | ||
| 9576 | } else { | ||
| 9577 | 236582 | templ->clust_rec_field_no = v_no; | |
| 9578 | // Prefix optimisation on generated column indexes is not | ||
| 9579 | // currently supported | ||
| 9580 | 236582 | templ->rec_field_is_prefix = false; | |
| 9581 | 236582 | templ->rec_prefix_field_no = ULINT_UNDEFINED; | |
| 9582 |
2/2✓ Branch 0 taken 234719 times.
✓ Branch 1 taken 1913 times.
|
236582 | if (index->is_clustered()) { |
| 9583 | 234719 | templ->rec_field_no = templ->clust_rec_field_no; | |
| 9584 | } else { | ||
| 9585 | 1913 | templ->rec_field_no = index->get_col_pos(v_no, false, true); | |
| 9586 | } | ||
| 9587 | } | ||
| 9588 | |||
| 9589 | /* Set in set_templ_icp(). */ | ||
| 9590 | 2005653649 | templ->icp_rec_field_no = ULINT_UNDEFINED; | |
| 9591 | |||
| 9592 |
2/2✓ Branch 0 taken 910002280 times.
✓ Branch 1 taken 1095649524 times.
|
2005653649 | if (field->is_nullable()) { |
| 9593 | 910002280 | templ->mysql_null_byte_offset = field->null_offset(); | |
| 9594 | |||
| 9595 | 910005656 | templ->mysql_null_bit_mask = (ulint)field->null_bit; | |
| 9596 | } else { | ||
| 9597 | 1095649524 | templ->mysql_null_bit_mask = 0; | |
| 9598 | } | ||
| 9599 | |||
| 9600 | 2005655180 | templ->mysql_col_offset = (ulint)get_field_offset(table, field); | |
| 9601 | 2005651203 | templ->mysql_col_len = (ulint)field->pack_length(); | |
| 9602 |
6/6✓ Branch 0 taken 236632 times.
✓ Branch 1 taken 2005411655 times.
✓ Branch 2 taken 2139 times.
✓ Branch 3 taken 234493 times.
✓ Branch 4 taken 2139 times.
✓ Branch 5 taken 2005646148 times.
|
2005648287 | if (templ->is_virtual && innobase_is_multi_value_fld(field)) { |
| 9603 | 2139 | templ->mysql_mvidx_len = static_cast<ulint>(field->key_length()); | |
| 9604 | 2139 | templ->is_multi_val = true; | |
| 9605 | } else { | ||
| 9606 | 2005646148 | templ->mysql_mvidx_len = 0; | |
| 9607 | 2005646148 | templ->is_multi_val = false; | |
| 9608 | } | ||
| 9609 | 2005648287 | templ->type = col->mtype; | |
| 9610 | 2005648287 | templ->mysql_type = (ulint)field->type(); | |
| 9611 | |||
| 9612 |
2/2✓ Branch 0 taken 408155829 times.
✓ Branch 1 taken 1597492622 times.
|
2005648451 | if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { |
| 9613 | 408155829 | templ->mysql_length_bytes = field->get_length_bytes(); | |
| 9614 | } else { | ||
| 9615 | 1597492622 | templ->mysql_length_bytes = 0; | |
| 9616 | } | ||
| 9617 | |||
| 9618 | 2005652121 | templ->charset = dtype_get_charset_coll(col->prtype); | |
| 9619 | 2005648967 | templ->mbminlen = col->get_mbminlen(); | |
| 9620 | 2005649173 | templ->mbmaxlen = col->get_mbmaxlen(); | |
| 9621 | 2005650434 | templ->is_unsigned = col->prtype & DATA_UNSIGNED; | |
| 9622 | 2005650434 | templ->compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED); | |
| 9623 | 2005650090 | templ->zip_dict_data = field->zip_dict_data; | |
| 9624 | |||
| 9625 |
6/6✓ Branch 0 taken 1066950448 times.
✓ Branch 1 taken 938701815 times.
✓ Branch 2 taken 853159622 times.
✓ Branch 3 taken 213790826 times.
✓ Branch 4 taken 853159629 times.
✓ Branch 5 taken 1152492634 times.
|
2005650090 | if (!index->is_clustered() && templ->rec_field_no == ULINT_UNDEFINED) { |
| 9626 | 853159629 | prebuilt->need_to_access_clustered = true; | |
| 9627 | } | ||
| 9628 | |||
| 9629 | /* For spatial index, we need to access cluster index. */ | ||
| 9630 |
2/2✓ Branch 0 taken 692 times.
✓ Branch 1 taken 2005645738 times.
|
2005652263 | if (dict_index_is_spatial(index)) { |
| 9631 | 692 | prebuilt->need_to_access_clustered = true; | |
| 9632 | } | ||
| 9633 | |||
| 9634 | 2005646430 | if (prebuilt->mysql_prefix_len < | |
| 9635 |
2/2✓ Branch 0 taken 2005596811 times.
✓ Branch 1 taken 49619 times.
|
2005646430 | templ->mysql_col_offset + templ->mysql_col_len) { |
| 9636 | 2005596811 | prebuilt->mysql_prefix_len = templ->mysql_col_offset + templ->mysql_col_len; | |
| 9637 | } | ||
| 9638 | |||
| 9639 |
2/2✓ Branch 0 taken 410448216 times.
✓ Branch 1 taken 1595198342 times.
|
2005646430 | if (DATA_LARGE_MTYPE(templ->type)) { |
| 9640 | 410448216 | prebuilt->templ_contains_blob = true; | |
| 9641 | } | ||
| 9642 | |||
| 9643 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2005646558 times.
|
2005646558 | if (templ->type == DATA_POINT) { |
| 9644 | /* We set this only when it's DATA_POINT, but not | ||
| 9645 | DATA_VAR_POINT */ | ||
| 9646 | ✗ | prebuilt->templ_contains_fixed_point = true; | |
| 9647 | } | ||
| 9648 | |||
| 9649 | 2005646558 | return (templ); | |
| 9650 | } | ||
| 9651 | |||
| 9652 | /** Set Index Condition Push down (ICP) field number in template. | ||
| 9653 | @param[in,out] templ mysql column template | ||
| 9654 | @param[in] index index used to build the template | ||
| 9655 | @param[in] scan_index active index for current scan | ||
| 9656 | @param[in] col_position position of current column */ | ||
| 9657 | 11151 | static void set_templ_icp(mysql_row_templ_t *templ, const dict_index_t *index, | |
| 9658 | const dict_index_t *scan_index, ulint col_position) { | ||
| 9659 |
2/4✓ Branch 0 taken 11151 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11151 times.
|
11151 | if (scan_index == nullptr || templ == nullptr) { |
| 9660 | ✗ | return; | |
| 9661 | } | ||
| 9662 | |||
| 9663 | 11151 | bool is_virtual = templ->is_virtual; | |
| 9664 | 11151 | auto icp_field_no = templ->rec_field_no; | |
| 9665 | |||
| 9666 |
2/2✓ Branch 0 taken 384 times.
✓ Branch 1 taken 10767 times.
|
11151 | if (scan_index != index) { |
| 9667 | /* First, try to find the column position without prefix. */ | ||
| 9668 | 384 | icp_field_no = scan_index->get_col_pos(col_position, false, is_virtual); | |
| 9669 | } | ||
| 9670 | |||
| 9671 | /* Try any prefix of the column. Used in end_range comparison. */ | ||
| 9672 |
2/2✓ Branch 0 taken 420 times.
✓ Branch 1 taken 10731 times.
|
11151 | if (icp_field_no == ULINT_UNDEFINED) { |
| 9673 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 420 times.
|
420 | ut_ad(!scan_index->is_clustered()); |
| 9674 | 420 | icp_field_no = scan_index->get_col_pos(col_position, true, is_virtual); | |
| 9675 | } | ||
| 9676 | 11151 | templ->icp_rec_field_no = icp_field_no; | |
| 9677 | } | ||
| 9678 | |||
| 9679 | /** Builds a 'template' to the m_prebuilt struct. The template is used in fast | ||
| 9680 | retrieval of just those column values MySQL needs in its processing. | ||
| 9681 | @param[in] whole_row true if access is needed to a whole row, false if accessing | ||
| 9682 | individual fields is enough */ | ||
| 9683 | 162851575 | void ha_innobase::build_template(bool whole_row) { | |
| 9684 | dict_index_t *index; | ||
| 9685 | dict_index_t *clust_index; | ||
| 9686 | ulint n_fields; | ||
| 9687 | 162851575 | bool fetch_all_in_key = false; | |
| 9688 | 162851575 | bool fetch_primary_key_cols = false; | |
| 9689 | ulint i; | ||
| 9690 | |||
| 9691 |
2/2✓ Branch 0 taken 38017640 times.
✓ Branch 1 taken 124833935 times.
|
162851575 | if (m_prebuilt->select_lock_type == LOCK_X) { |
| 9692 | /* We always retrieve the whole clustered index record if we | ||
| 9693 | use exclusive row level locks, for example, if the read is | ||
| 9694 | done in an UPDATE statement. */ | ||
| 9695 | |||
| 9696 | 38017640 | whole_row = true; | |
| 9697 |
2/2✓ Branch 0 taken 124743965 times.
✓ Branch 1 taken 89970 times.
|
124833935 | } else if (!whole_row) { |
| 9698 |
2/2✓ Branch 0 taken 240 times.
✓ Branch 1 taken 124743725 times.
|
124743965 | if (m_prebuilt->hint_need_to_fetch_extra_cols == ROW_RETRIEVE_ALL_COLS) { |
| 9699 | /* We know we must at least fetch all columns in the | ||
| 9700 | key, or all columns in the table */ | ||
| 9701 | |||
| 9702 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
|
240 | if (m_prebuilt->read_just_key) { |
| 9703 | /* MySQL has instructed us that it is enough | ||
| 9704 | to fetch the columns in the key; looks like | ||
| 9705 | MySQL can set this flag also when there is | ||
| 9706 | only a prefix of the column in the key: in | ||
| 9707 | that case we retrieve the whole column from | ||
| 9708 | the clustered index */ | ||
| 9709 | |||
| 9710 | ✗ | fetch_all_in_key = true; | |
| 9711 | } else { | ||
| 9712 | 240 | whole_row = true; | |
| 9713 | } | ||
| 9714 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 124743725 times.
|
124743725 | } else if (m_prebuilt->hint_need_to_fetch_extra_cols == |
| 9715 | ROW_RETRIEVE_PRIMARY_KEY) { | ||
| 9716 | /* We must at least fetch all primary key cols. Note | ||
| 9717 | that if the clustered index was internally generated | ||
| 9718 | by InnoDB on the row id (no primary key was | ||
| 9719 | defined), then row_search_for_mysql() will always | ||
| 9720 | retrieve the row id to a special buffer in the | ||
| 9721 | m_prebuilt struct. */ | ||
| 9722 | |||
| 9723 | ✗ | fetch_primary_key_cols = true; | |
| 9724 | } | ||
| 9725 | } | ||
| 9726 | |||
| 9727 | 162851575 | clust_index = m_prebuilt->table->first_index(); | |
| 9728 | |||
| 9729 |
2/2✓ Branch 0 taken 38108151 times.
✓ Branch 1 taken 124743794 times.
|
162851945 | index = whole_row ? clust_index : m_prebuilt->index; |
| 9730 | |||
| 9731 | 162851945 | m_prebuilt->need_to_access_clustered = (index == clust_index); | |
| 9732 | |||
| 9733 | /* Either m_prebuilt->index should be a secondary index, or it | ||
| 9734 | should be the clustered index. */ | ||
| 9735 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 162851897 times.
|
162851945 | ut_ad(index->is_clustered() == (index == clust_index)); |
| 9736 | |||
| 9737 | /* Below we check column by column if we need to access | ||
| 9738 | the clustered index. */ | ||
| 9739 | |||
| 9740 | 162851897 | n_fields = (ulint)table->s->fields; /* number of columns */ | |
| 9741 | |||
| 9742 |
2/2✓ Branch 0 taken 3351150 times.
✓ Branch 1 taken 159500747 times.
|
162851897 | if (!m_prebuilt->mysql_template) { |
| 9743 | 3351148 | m_prebuilt->mysql_template = (mysql_row_templ_t *)ut::malloc_withkey( | |
| 9744 | 3351150 | UT_NEW_THIS_FILE_PSI_KEY, n_fields * sizeof(mysql_row_templ_t)); | |
| 9745 | } | ||
| 9746 | |||
| 9747 | #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND) | ||
| 9748 | /* zero-filling for compare contents for debug */ | ||
| 9749 | 162851548 | memset(m_prebuilt->mysql_template, 0, n_fields * sizeof(mysql_row_templ_t)); | |
| 9750 | #endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */ | ||
| 9751 | |||
| 9752 | 162851548 | m_prebuilt->template_type = | |
| 9753 |
2/2✓ Branch 0 taken 38107892 times.
✓ Branch 1 taken 124743656 times.
|
162851548 | whole_row ? ROW_MYSQL_WHOLE_ROW : ROW_MYSQL_REC_FIELDS; |
| 9754 | 162851548 | m_prebuilt->null_bitmap_len = table->s->null_bytes; | |
| 9755 | |||
| 9756 | /* Prepare to build m_prebuilt->mysql_template[]. */ | ||
| 9757 | 162851548 | m_prebuilt->templ_contains_blob = false; | |
| 9758 | 162851548 | m_prebuilt->templ_contains_fixed_point = false; | |
| 9759 | 162851548 | m_prebuilt->mysql_prefix_len = 0; | |
| 9760 | 162851548 | m_prebuilt->n_template = 0; | |
| 9761 | 162851548 | m_prebuilt->idx_cond_n_cols = 0; | |
| 9762 | |||
| 9763 | /* Note that in InnoDB, i is the column number in the table. | ||
| 9764 | MySQL calls columns 'fields'. */ | ||
| 9765 | |||
| 9766 |
4/4✓ Branch 0 taken 153197995 times.
✓ Branch 1 taken 9653553 times.
✓ Branch 2 taken 5287 times.
✓ Branch 3 taken 153192708 times.
|
162851548 | if (active_index != MAX_KEY && active_index == pushed_idx_cond_keyno) { |
| 9767 | 5287 | ulint num_v = 0; | |
| 9768 | |||
| 9769 | /* Push down an index condition or an end_range check. */ | ||
| 9770 |
2/2✓ Branch 0 taken 24965 times.
✓ Branch 1 taken 5287 times.
|
30252 | for (i = 0; i < n_fields; i++) { |
| 9771 | bool index_contains; | ||
| 9772 | |||
| 9773 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24937 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
24965 | if (innobase_is_v_fld(table->field[i])) { |
| 9774 | 18 | index_contains = dict_index_contains_col_or_prefix(index, num_v, true); | |
| 9775 | } else { | ||
| 9776 | index_contains = | ||
| 9777 | 24947 | dict_index_contains_col_or_prefix(index, i - num_v, false); | |
| 9778 | } | ||
| 9779 | |||
| 9780 | /* Test if an end_range or an index condition | ||
| 9781 | refers to the field. Note that "index" and | ||
| 9782 | "index_contains" may refer to the clustered index. | ||
| 9783 | Index condition pushdown is relative to | ||
| 9784 | m_prebuilt->index (the index that is being | ||
| 9785 | looked up first). */ | ||
| 9786 | |||
| 9787 | /* When join_read_always_key() invokes this | ||
| 9788 | code via handler::ha_index_init() and | ||
| 9789 | ha_innobase::index_init(), end_range is not | ||
| 9790 | yet initialized. Because of that, we must | ||
| 9791 | always check for index_contains, instead of | ||
| 9792 | the subset | ||
| 9793 | field->part_of_key.is_set(active_index) | ||
| 9794 | which would be acceptable if end_range==NULL. */ | ||
| 9795 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24937 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
24965 | bool is_v = innobase_is_v_fld(table->field[i]); |
| 9796 |
4/4✓ Branch 0 taken 18 times.
✓ Branch 1 taken 24947 times.
✓ Branch 2 taken 10095 times.
✓ Branch 3 taken 14870 times.
|
24965 | if (build_template_needs_field_in_icp(index, m_prebuilt, index_contains, |
| 9797 | is_v ? num_v : i - num_v, is_v)) { | ||
| 9798 | /* Needed in ICP */ | ||
| 9799 | const Field *field; | ||
| 9800 | mysql_row_templ_t *templ; | ||
| 9801 | |||
| 9802 |
2/2✓ Branch 0 taken 148 times.
✓ Branch 1 taken 9947 times.
|
10095 | if (whole_row) { |
| 9803 | 148 | field = table->field[i]; | |
| 9804 | } else { | ||
| 9805 | 19894 | field = build_template_needs_field( | |
| 9806 | 9947 | index_contains, m_prebuilt->read_just_key, fetch_all_in_key, | |
| 9807 | 9947 | fetch_primary_key_cols, index, table, i, num_v); | |
| 9808 |
2/2✓ Branch 0 taken 1079 times.
✓ Branch 1 taken 8868 times.
|
9947 | if (!field) { |
| 9809 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1079 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1079 | if (innobase_is_v_fld(table->field[i])) { |
| 9810 | ✗ | num_v++; | |
| 9811 | } | ||
| 9812 | 1079 | continue; | |
| 9813 | } | ||
| 9814 | } | ||
| 9815 | |||
| 9816 | 9016 | templ = build_template_field(m_prebuilt, clust_index, index, table, | |
| 9817 | field, i - num_v, 0); | ||
| 9818 | |||
| 9819 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9016 times.
|
9016 | ut_ad(!templ->is_virtual); |
| 9820 | |||
| 9821 | 9016 | m_prebuilt->idx_cond_n_cols++; | |
| 9822 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9016 times.
|
9016 | ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template); |
| 9823 | |||
| 9824 | 9016 | auto column_position = i - num_v; | |
| 9825 | |||
| 9826 | 9016 | set_templ_icp(templ, index, m_prebuilt->index, column_position); | |
| 9827 | |||
| 9828 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9016 times.
|
9016 | ut_ad(templ->icp_rec_field_no != ULINT_UNDEFINED); |
| 9829 | |||
| 9830 | /* Index condition pushdown can be used on | ||
| 9831 | all columns of a secondary index, and on | ||
| 9832 | the PRIMARY KEY columns. On the clustered | ||
| 9833 | index, it must never be used on other than | ||
| 9834 | PRIMARY KEY columns, because those columns | ||
| 9835 | may be stored off-page, and we will not | ||
| 9836 | fetch externally stored columns before | ||
| 9837 | checking the index condition. */ | ||
| 9838 | /* TODO: test the above with an assertion | ||
| 9839 | like this. Note that index conditions are | ||
| 9840 | currently pushed down as part of the | ||
| 9841 | "optimizer phase" while end_range is done | ||
| 9842 | as part of the execution phase. Therefore, | ||
| 9843 | we were unable to use an accurate condition | ||
| 9844 | for end_range in the "if" condition above, | ||
| 9845 | and the following assertion would fail. | ||
| 9846 | ut_ad(!(m_prebuilt->index->is_clustered()) | ||
| 9847 | || templ->rec_field_no | ||
| 9848 | < m_prebuilt->index->n_uniq); | ||
| 9849 | */ | ||
| 9850 | } | ||
| 9851 | |||
| 9852 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 23858 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
23886 | if (innobase_is_v_fld(table->field[i])) { |
| 9853 | 18 | num_v++; | |
| 9854 | } | ||
| 9855 | } | ||
| 9856 | |||
| 9857 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5287 times.
|
5287 | ut_ad(m_prebuilt->idx_cond_n_cols > 0); |
| 9858 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5287 times.
|
5287 | ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template); |
| 9859 | |||
| 9860 | 5287 | num_v = 0; | |
| 9861 | |||
| 9862 | /* Include the fields that are not needed in index condition | ||
| 9863 | pushdown. */ | ||
| 9864 |
2/2✓ Branch 0 taken 24965 times.
✓ Branch 1 taken 5287 times.
|
30252 | for (i = 0; i < n_fields; i++) { |
| 9865 | mysql_row_templ_t *templ; | ||
| 9866 | bool index_contains; | ||
| 9867 | |||
| 9868 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24937 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
24965 | if (innobase_is_v_fld(table->field[i])) { |
| 9869 | 18 | index_contains = dict_index_contains_col_or_prefix(index, num_v, true); | |
| 9870 | } else { | ||
| 9871 | index_contains = | ||
| 9872 | 24947 | dict_index_contains_col_or_prefix(index, i - num_v, false); | |
| 9873 | } | ||
| 9874 | |||
| 9875 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24937 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
24965 | bool is_v = innobase_is_v_fld(table->field[i]); |
| 9876 | |||
| 9877 |
4/4✓ Branch 0 taken 18 times.
✓ Branch 1 taken 24947 times.
✓ Branch 2 taken 14870 times.
✓ Branch 3 taken 10095 times.
|
24965 | if (!build_template_needs_field_in_icp(index, m_prebuilt, index_contains, |
| 9878 | is_v ? num_v : i - num_v, is_v)) { | ||
| 9879 | /* Not needed in ICP */ | ||
| 9880 | const Field *field; | ||
| 9881 | |||
| 9882 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 14814 times.
|
14870 | if (whole_row) { |
| 9883 | 56 | field = table->field[i]; | |
| 9884 | } else { | ||
| 9885 | 29628 | field = build_template_needs_field( | |
| 9886 | 14814 | index_contains, m_prebuilt->read_just_key, fetch_all_in_key, | |
| 9887 | 14814 | fetch_primary_key_cols, index, table, i, num_v); | |
| 9888 |
2/2✓ Branch 0 taken 3570 times.
✓ Branch 1 taken 11244 times.
|
14814 | if (!field) { |
| 9889 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3566 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
3570 | if (innobase_is_v_fld(table->field[i])) { |
| 9890 | 4 | num_v++; | |
| 9891 | } | ||
| 9892 | 3570 | continue; | |
| 9893 | } | ||
| 9894 | } | ||
| 9895 | |||
| 9896 | 11300 | templ = build_template_field(m_prebuilt, clust_index, index, table, | |
| 9897 | field, i - num_v, num_v); | ||
| 9898 | |||
| 9899 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 11286 times.
|
11300 | if (templ->is_virtual) { |
| 9900 | 14 | num_v++; | |
| 9901 | } | ||
| 9902 | } | ||
| 9903 | } | ||
| 9904 | |||
| 9905 | 5287 | m_prebuilt->idx_cond = true; | |
| 9906 | 5287 | } else { | |
| 9907 | mysql_row_templ_t *templ; | ||
| 9908 | 162846261 | ulint num_v = 0; | |
| 9909 | /* No index condition pushdown */ | ||
| 9910 | 162846261 | m_prebuilt->idx_cond = false; | |
| 9911 | |||
| 9912 |
2/2✓ Branch 0 taken 2064651392 times.
✓ Branch 1 taken 162843332 times.
|
2227494724 | for (i = 0; i < n_fields; i++) { |
| 9913 | const Field *field; | ||
| 9914 |
4/4✓ Branch 0 taken 437633 times.
✓ Branch 1 taken 2064213759 times.
✓ Branch 2 taken 413096 times.
✓ Branch 3 taken 24537 times.
|
2064651392 | bool is_virtual = innobase_is_v_fld(table->field[i]); |
| 9915 | |||
| 9916 |
2/2✓ Branch 0 taken 522783559 times.
✓ Branch 1 taken 1541867833 times.
|
2064651392 | if (whole_row) { |
| 9917 | /* Even this is whole_row, if the seach is | ||
| 9918 | on a virtual column, and read_just_key is | ||
| 9919 | set, and field is not in this index, we | ||
| 9920 | will not try to fill the value since they | ||
| 9921 | are not stored in such index nor in the | ||
| 9922 | cluster index. */ | ||
| 9923 |
5/6✓ Branch 0 taken 55586 times.
✓ Branch 1 taken 522727973 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 55580 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 522783559 times.
|
522783565 | if (is_virtual && m_prebuilt->read_just_key && |
| 9924 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | !dict_index_contains_col_or_prefix(m_prebuilt->index, num_v, |
| 9925 | true)) { | ||
| 9926 | /* Turn off ROW_MYSQL_WHOLE_ROW */ | ||
| 9927 | ✗ | m_prebuilt->template_type = ROW_MYSQL_REC_FIELDS; | |
| 9928 | ✗ | num_v++; | |
| 9929 | ✗ | continue; | |
| 9930 | } | ||
| 9931 | |||
| 9932 | 522783559 | field = table->field[i]; | |
| 9933 | } else { | ||
| 9934 | bool contain; | ||
| 9935 | |||
| 9936 |
4/4✓ Branch 0 taken 364504 times.
✓ Branch 1 taken 1541503329 times.
✓ Branch 2 taken 357510 times.
✓ Branch 3 taken 6994 times.
|
1541867833 | if (innobase_is_v_fld(table->field[i])) { |
| 9937 | 357510 | contain = dict_index_contains_col_or_prefix(index, num_v, true); | |
| 9938 | } else { | ||
| 9939 | 1541510323 | contain = dict_index_contains_col_or_prefix(index, i - num_v, false); | |
| 9940 | } | ||
| 9941 | |||
| 9942 | 3083735869 | field = build_template_needs_field( | |
| 9943 | 1541866498 | contain, m_prebuilt->read_just_key, fetch_all_in_key, | |
| 9944 | 1541866498 | fetch_primary_key_cols, index, table, i, num_v); | |
| 9945 |
2/2✓ Branch 0 taken 59024527 times.
✓ Branch 1 taken 1482844844 times.
|
1541869371 | if (!field) { |
| 9946 |
2/2✓ Branch 0 taken 176478 times.
✓ Branch 1 taken 58848049 times.
|
59024527 | if (is_virtual) { |
| 9947 | 176478 | num_v++; | |
| 9948 | } | ||
| 9949 | 59024527 | continue; | |
| 9950 | } | ||
| 9951 | } | ||
| 9952 | |||
| 9953 | 2005628403 | templ = build_template_field(m_prebuilt, clust_index, index, table, field, | |
| 9954 | i - num_v, num_v); | ||
| 9955 | |||
| 9956 | /* Virtual columns may have to be read from the secondary index before | ||
| 9957 | evaluating an end-range condition in row_search_end_range_check(). Set | ||
| 9958 | ICP field number for virtual column. */ | ||
| 9959 | 2005626126 | auto scan_index = m_prebuilt->index; | |
| 9960 |
4/4✓ Branch 0 taken 2002875211 times.
✓ Branch 1 taken 2750915 times.
✓ Branch 2 taken 1122010052 times.
✓ Branch 3 taken 880865889 times.
|
2005626126 | bool is_sec_idx = (scan_index != nullptr && !scan_index->is_clustered()); |
| 9961 | |||
| 9962 |
4/4✓ Branch 0 taken 236618 times.
✓ Branch 1 taken 2005390238 times.
✓ Branch 2 taken 2135 times.
✓ Branch 3 taken 234483 times.
|
2005626856 | if (is_virtual && is_sec_idx) { |
| 9963 | 2135 | set_templ_icp(templ, index, scan_index, num_v); | |
| 9964 | } | ||
| 9965 | |||
| 9966 |
2/2✓ Branch 0 taken 236618 times.
✓ Branch 1 taken 2005387318 times.
|
2005623936 | if (templ->is_virtual) { |
| 9967 | 236618 | num_v++; | |
| 9968 | } | ||
| 9969 | } | ||
| 9970 | } | ||
| 9971 | |||
| 9972 |
4/4✓ Branch 0 taken 64843957 times.
✓ Branch 1 taken 98004662 times.
✓ Branch 2 taken 60657791 times.
✓ Branch 3 taken 4186166 times.
|
162848619 | if (index != clust_index && m_prebuilt->need_to_access_clustered) { |
| 9973 | /* Change rec_field_no's to correspond to the clustered index | ||
| 9974 | record */ | ||
| 9975 |
2/2✓ Branch 0 taken 1054546849 times.
✓ Branch 1 taken 60657791 times.
|
1115204640 | for (i = 0; i < m_prebuilt->n_template; i++) { |
| 9976 | 1054546849 | mysql_row_templ_t *templ = &m_prebuilt->mysql_template[i]; | |
| 9977 | |||
| 9978 | 1054546849 | templ->rec_field_no = templ->clust_rec_field_no; | |
| 9979 | } | ||
| 9980 | } | ||
| 9981 | 162848619 | } | |
| 9982 | |||
| 9983 | /** This special handling is really to overcome the limitations of MySQL's | ||
| 9984 | binlogging. We need to eliminate the non-determinism that will arise in | ||
| 9985 | INSERT ... SELECT type of statements, since MySQL binlog only stores the | ||
| 9986 | min value of the autoinc interval. Once that is fixed we can get rid of | ||
| 9987 | the special lock handling. | ||
| 9988 | @return DB_SUCCESS if all OK else error code */ | ||
| 9989 | |||
| 9990 | 8497243 | dberr_t ha_innobase::innobase_lock_autoinc(void) { | |
| 9991 |
1/2✓ Branch 0 taken 8497429 times.
✗ Branch 1 not taken.
|
8497243 | DBUG_TRACE; |
| 9992 | 8497429 | dberr_t error = DB_SUCCESS; | |
| 9993 | 8497429 | long lock_mode = innobase_autoinc_lock_mode; | |
| 9994 | |||
| 9995 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 8497429 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8497344 times.
|
8497429 | ut_ad(!srv_read_only_mode || m_prebuilt->table->is_intrinsic()); |
| 9996 | |||
| 9997 |
7/8✓ Branch 0 taken 8497402 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8497310 times.
✓ Branch 3 taken 92 times.
✓ Branch 4 taken 6604787 times.
✓ Branch 5 taken 1892523 times.
✓ Branch 6 taken 6604818 times.
✓ Branch 7 taken 1892584 times.
|
8497344 | if (m_prebuilt->table->is_intrinsic() || m_prebuilt->no_autoinc_locking) { |
| 9998 | /* Intrinsic table are not shared across connection | ||
| 9999 | so there is no need to AUTOINC lock the table. | ||
| 10000 | Also we won't use AUTOINC lock if this was requested | ||
| 10001 | explicitly. */ | ||
| 10002 | 6604818 | lock_mode = AUTOINC_NO_LOCKING; | |
| 10003 | } | ||
| 10004 | |||
| 10005 |
3/4✓ Branch 0 taken 8487356 times.
✓ Branch 1 taken 1003 times.
✓ Branch 2 taken 9043 times.
✗ Branch 3 not taken.
|
8497402 | switch (lock_mode) { |
| 10006 | 8487356 | case AUTOINC_NO_LOCKING: | |
| 10007 | /* Acquire only the AUTOINC mutex. */ | ||
| 10008 |
1/2✓ Branch 0 taken 8487399 times.
✗ Branch 1 not taken.
|
8487356 | dict_table_autoinc_lock(m_prebuilt->table); |
| 10009 | 8487399 | break; | |
| 10010 | |||
| 10011 | 1003 | case AUTOINC_NEW_STYLE_LOCKING: | |
| 10012 | /* For simple (single/multi) row INSERTs, we fallback to the | ||
| 10013 | old style only if another transaction has already acquired | ||
| 10014 | the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT | ||
| 10015 | etc. type of statement. */ | ||
| 10016 |
5/6✓ Branch 0 taken 1003 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 315 times.
✓ Branch 3 taken 688 times.
✓ Branch 4 taken 687 times.
✓ Branch 5 taken 316 times.
|
1318 | if (thd_sql_command(m_user_thd) == SQLCOM_INSERT || |
| 10017 |
2/4✓ Branch 0 taken 315 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 315 times.
|
315 | thd_sql_command(m_user_thd) == SQLCOM_REPLACE) { |
| 10018 | 687 | dict_table_t *ib_table = m_prebuilt->table; | |
| 10019 | |||
| 10020 | /* Acquire the AUTOINC mutex. */ | ||
| 10021 |
1/2✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
|
687 | dict_table_autoinc_lock(ib_table); |
| 10022 | |||
| 10023 |
2/4✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 688 times.
✗ Branch 3 not taken.
|
688 | DEBUG_SYNC_C("innobase_lock_autoinc"); |
| 10024 | |||
| 10025 | /* We need to check that another transaction isn't | ||
| 10026 | already holding the AUTOINC lock on the table. */ | ||
| 10027 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 688 times.
|
688 | if (ib_table->count_by_mode[LOCK_AUTO_INC]) { |
| 10028 | /* Release the mutex to avoid deadlocks. */ | ||
| 10029 | ✗ | dict_table_autoinc_unlock(ib_table); | |
| 10030 | } else { | ||
| 10031 | 688 | break; | |
| 10032 | } | ||
| 10033 | } | ||
| 10034 | /* Fall through to old style locking. */ | ||
| 10035 | [[fallthrough]]; | ||
| 10036 | |||
| 10037 | case AUTOINC_OLD_STYLE_LOCKING: | ||
| 10038 |
2/4✓ Branch 0 taken 9312 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9312 times.
|
9359 | DBUG_EXECUTE_IF("die_if_autoinc_old_lock_style_used", ut_d(ut_error);); |
| 10039 |
1/2✓ Branch 0 taken 9314 times.
✗ Branch 1 not taken.
|
9312 | error = row_lock_table_autoinc_for_mysql(m_prebuilt); |
| 10040 | |||
| 10041 |
2/2✓ Branch 0 taken 9313 times.
✓ Branch 1 taken 1 times.
|
9314 | if (error == DB_SUCCESS) { |
| 10042 | /* Acquire the AUTOINC mutex. */ | ||
| 10043 |
1/2✓ Branch 0 taken 9313 times.
✗ Branch 1 not taken.
|
9313 | dict_table_autoinc_lock(m_prebuilt->table); |
| 10044 | } | ||
| 10045 | 9314 | break; | |
| 10046 | |||
| 10047 | ✗ | default: | |
| 10048 | ✗ | ut_error; | |
| 10049 | } | ||
| 10050 | |||
| 10051 | 8497430 | return error; | |
| 10052 | 8497401 | } | |
| 10053 | |||
| 10054 | /** Store the autoinc value in the table. The autoinc value is only set if | ||
| 10055 | it's greater than the existing autoinc value in the table. | ||
| 10056 | @return DB_SUCCESS if all went well else error code */ | ||
| 10057 | |||
| 10058 | 1439762 | dberr_t ha_innobase::innobase_set_max_autoinc( | |
| 10059 | ulonglong auto_inc) /*!< in: value to store */ | ||
| 10060 | { | ||
| 10061 | dberr_t error; | ||
| 10062 | |||
| 10063 | 1439762 | error = innobase_lock_autoinc(); | |
| 10064 | |||
| 10065 |
1/2✓ Branch 0 taken 1439762 times.
✗ Branch 1 not taken.
|
1439762 | if (error == DB_SUCCESS) { |
| 10066 | 1439762 | dict_table_autoinc_update_if_greater(m_prebuilt->table, auto_inc); | |
| 10067 | |||
| 10068 | 1439762 | dict_table_autoinc_unlock(m_prebuilt->table); | |
| 10069 | } | ||
| 10070 | |||
| 10071 | 1439762 | return (error); | |
| 10072 | } | ||
| 10073 | |||
| 10074 | /** Write Row interface optimized for intrinisc table. | ||
| 10075 | @param[in] record a row in MySQL format. | ||
| 10076 | @return 0 on success or error code */ | ||
| 10077 | 13654241 | int ha_innobase::intrinsic_table_write_row(uchar *record) { | |
| 10078 | dberr_t err; | ||
| 10079 | |||
| 10080 | /* No auto-increment support for intrinsic table. */ | ||
| 10081 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 13654241 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13654241 times.
|
13654241 | ut_ad(!(table->next_number_field && record == table->record[0])); |
| 10082 | |||
| 10083 |
2/2✓ Branch 0 taken 13600439 times.
✓ Branch 1 taken 53802 times.
|
13654241 | if (m_prebuilt->mysql_template == nullptr || |
| 10084 |
2/2✓ Branch 0 taken 24730 times.
✓ Branch 1 taken 13575709 times.
|
13600439 | m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) { |
| 10085 | /* Build the template used in converting quickly between | ||
| 10086 | the two database formats */ | ||
| 10087 | 78532 | build_template(true); | |
| 10088 | } | ||
| 10089 | |||
| 10090 | 13654241 | err = row_insert_for_mysql((byte *)record, m_prebuilt); | |
| 10091 | |||
| 10092 | return ( | ||
| 10093 | 13654241 | convert_error_code_to_mysql(err, m_prebuilt->table->flags, m_user_thd)); | |
| 10094 | } | ||
| 10095 | |||
| 10096 | /** Parse out multi-value and store in a multi_value_data struct | ||
| 10097 | @param[in] bv JSON binary that has the mult-value | ||
| 10098 | @param[out] valuep store the parsed out value | ||
| 10099 | @param[in] fld Array Field for the data | ||
| 10100 | @param[in] dfield InnoDB indexed field struct | ||
| 10101 | @param[in] comp if this is new InnoDB row type | ||
| 10102 | @param[in,out] heap heap memory */ | ||
| 10103 | 26278 | static void innobase_store_multi_value_low(json_binary::Value *bv, | |
| 10104 | multi_value_data **valuep, | ||
| 10105 | Field_typed_array *fld, | ||
| 10106 | dfield_t *dfield, ulint comp, | ||
| 10107 | mem_heap_t *heap) { | ||
| 10108 | 26278 | multi_value_data *value = *valuep; | |
| 10109 | byte *buf; | ||
| 10110 | |||
| 10111 | /* Even for single values, there will be an array with 1 element */ | ||
| 10112 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26278 times.
|
26278 | ut_ad(bv->type() == json_binary::Value::ARRAY); |
| 10113 | 26278 | uint32_t elements = bv->element_count(); | |
| 10114 | |||
| 10115 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26278 times.
|
26278 | ut_ad(elements > 0); |
| 10116 | |||
| 10117 |
2/2✓ Branch 0 taken 25587 times.
✓ Branch 1 taken 691 times.
|
26278 | if (value == nullptr) { |
| 10118 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25587 times.
|
25587 | ut_ad(heap != nullptr); |
| 10119 | value = | ||
| 10120 | 25587 | static_cast<multi_value_data *>(mem_heap_zalloc(heap, sizeof(*value))); | |
| 10121 | } | ||
| 10122 | |||
| 10123 |
2/2✓ Branch 0 taken 25588 times.
✓ Branch 1 taken 690 times.
|
26278 | if (elements > value->num_alc) { |
| 10124 | 25588 | value->alloc(elements, false, heap); | |
| 10125 | } | ||
| 10126 | |||
| 10127 | 26278 | buf = reinterpret_cast<byte *>(value->conv_buf); | |
| 10128 | |||
| 10129 | 26278 | value->num_v = elements; | |
| 10130 | |||
| 10131 | 26278 | ulint col_len = fld->key_length(); | |
| 10132 | |||
| 10133 |
2/2✓ Branch 0 taken 254894 times.
✓ Branch 1 taken 26278 times.
|
281172 | for (uint i = 0; i < elements; i++) { |
| 10134 | 254894 | const byte *mysql_data = nullptr; | |
| 10135 |
1/2✓ Branch 0 taken 254894 times.
✗ Branch 1 not taken.
|
254894 | const dtype_t *dtype = dfield_get_type(dfield); |
| 10136 | 254894 | ulint type = dtype->mtype; | |
| 10137 | int64_t val; | ||
| 10138 | |||
| 10139 |
1/2✓ Branch 0 taken 254894 times.
✗ Branch 1 not taken.
|
254894 | json_binary::Value elt = bv->element(i); |
| 10140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 254894 times.
|
254894 | if (elt.type() == json_binary::Value::LITERAL_NULL) { |
| 10141 | ✗ | dfield_set_data(dfield, nullptr, UNIV_SQL_NULL); | |
| 10142 |
2/2✓ Branch 0 taken 253459 times.
✓ Branch 1 taken 1435 times.
|
254894 | } else if (type == DATA_INT) { |
| 10143 | byte data[8]; | ||
| 10144 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 253381 times.
|
253459 | if (elt.type() == json_binary::Value::OPAQUE) { |
| 10145 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
156 | if (elt.field_type() == MYSQL_TYPE_TIME || |
| 10146 |
3/6✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 78 times.
|
156 | elt.field_type() == MYSQL_TYPE_DATETIME || |
| 10147 | 78 | elt.field_type() == MYSQL_TYPE_TIMESTAMP) { | |
| 10148 | /* Newer Mysql temporal types use DATA_FIXBINARY Innodb type */ | ||
| 10149 | ✗ | ut_d(ut_error); /* purecov: inspected */ | |
| 10150 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | } else if (elt.field_type() == MYSQL_TYPE_DATE) { |
| 10151 | /* Temporal data has at most 8 bytes length */ | ||
| 10152 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | Json_datetime::from_packed_to_key(elt.get_data(), elt.field_type(), |
| 10153 | 78 | data, fld->decimals()); | |
| 10154 | 78 | mysql_data = data; | |
| 10155 | } else { | ||
| 10156 | ✗ | mysql_data = reinterpret_cast<const byte *>(elt.get_data()); | |
| 10157 | } | ||
| 10158 | } else { | ||
| 10159 | /* Both signed and unsigned ints are handled here. Because there is | ||
| 10160 | an assumption the data passed from server should be always | ||
| 10161 | little-endian one, so need to convert it explicitly here. | ||
| 10162 | @see Field_longlong::store() */ | ||
| 10163 |
2/2✓ Branch 0 taken 253101 times.
✓ Branch 1 taken 280 times.
|
253381 | if (fld->is_unsigned()) { |
| 10164 | 253101 | val = static_cast<int64_t>(elt.get_uint64()); | |
| 10165 | } else { | ||
| 10166 | 280 | val = elt.get_int64(); | |
| 10167 | } | ||
| 10168 | #ifdef WORDS_BIGENDIAN | ||
| 10169 | if (fld->table->s->db_low_byte_first) { | ||
| 10170 | int8store(data, val); | ||
| 10171 | } else | ||
| 10172 | #endif | ||
| 10173 | { | ||
| 10174 | 253381 | longlongstore(data, val); | |
| 10175 | } | ||
| 10176 | 253381 | mysql_data = data; | |
| 10177 | } | ||
| 10178 |
1/2✓ Branch 0 taken 253459 times.
✗ Branch 1 not taken.
|
253459 | row_mysql_store_col_in_innobase_format(dfield, buf, true, mysql_data, |
| 10179 | col_len, comp, false, nullptr, 0, | ||
| 10180 | nullptr); | ||
| 10181 |
4/6✓ Branch 0 taken 1435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1435 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 549 times.
✓ Branch 5 taken 886 times.
|
1435 | } else if (type == DATA_CHAR || type == DATA_VARCHAR || |
| 10182 | type == DATA_VARMYSQL) { | ||
| 10183 | 549 | mysql_data = (byte *)elt.get_data(); | |
| 10184 | 549 | col_len = (ulint)elt.get_data_length(); | |
| 10185 |
1/2✓ Branch 0 taken 549 times.
✗ Branch 1 not taken.
|
549 | dfield_set_data(dfield, mysql_data, col_len); |
| 10186 |
3/4✓ Branch 0 taken 494 times.
✓ Branch 1 taken 392 times.
✓ Branch 2 taken 494 times.
✗ Branch 3 not taken.
|
886 | } else if (type == DATA_BINARY || type == DATA_FIXBINARY) { |
| 10187 |
1/2✓ Branch 0 taken 886 times.
✗ Branch 1 not taken.
|
886 | if (elt.type() == json_binary::Value::OPAQUE) { |
| 10188 |
3/4✓ Branch 0 taken 392 times.
✓ Branch 1 taken 329 times.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
|
886 | switch (elt.field_type()) { |
| 10189 | 392 | case MYSQL_TYPE_VARCHAR: { | |
| 10190 | 392 | mysql_data = reinterpret_cast<const byte *>(elt.get_data()); | |
| 10191 |
1/2✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
|
392 | dfield_set_data(dfield, |
| 10192 | 392 | reinterpret_cast<const byte *>(elt.get_data()), | |
| 10193 | 392 | elt.get_data_length()); | |
| 10194 | 392 | break; | |
| 10195 | } | ||
| 10196 | 329 | case MYSQL_TYPE_NEWDECIMAL: { | |
| 10197 | 329 | ut_d(my_decimal d); | |
| 10198 | /* Ensure correct decimal value */ | ||
| 10199 |
2/4✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 329 times.
|
329 | ut_ad(!Json_decimal::convert_from_binary( |
| 10200 | elt.get_data(), elt.get_data_length(), &d)); | ||
| 10201 | /* Ensure binary is of the expected size */ | ||
| 10202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 329 times.
|
329 | ut_ad(Json_decimal::get_encoded_binary_len(elt.get_data_length()) == |
| 10203 | dfield->type.len); | ||
| 10204 |
1/2✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
|
329 | dfield_set_data(dfield, |
| 10205 | 329 | Json_decimal::get_encoded_binary(elt.get_data()), | |
| 10206 | 329 | dfield->type.len); | |
| 10207 | 329 | break; | |
| 10208 | 329 | } | |
| 10209 | 165 | case MYSQL_TYPE_TIME: | |
| 10210 | case MYSQL_TYPE_DATE: | ||
| 10211 | case MYSQL_TYPE_DATETIME: | ||
| 10212 | case MYSQL_TYPE_TIMESTAMP: { | ||
| 10213 | /* Temporal data has at most 8 bytes length */ | ||
| 10214 |
1/2✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
|
165 | Json_datetime::from_packed_to_key(elt.get_data(), elt.field_type(), |
| 10215 | 165 | buf, fld->decimals()); | |
| 10216 | |||
| 10217 |
1/2✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
|
165 | dfield_set_data(dfield, buf, dfield->type.len); |
| 10218 | 165 | break; | |
| 10219 | } | ||
| 10220 | ✗ | default: | |
| 10221 | /* Shouldn't happen */ | ||
| 10222 | ✗ | ut_d(ut_error); /* purecov: inspected */ | |
| 10223 | } | ||
| 10224 | } | ||
| 10225 | 886 | } else { | |
| 10226 | /* not supported */ | ||
| 10227 | ✗ | ut_d(ut_error); /* purecov: inspected */ | |
| 10228 | } | ||
| 10229 | |||
| 10230 | 254894 | value->datap[i] = dfield->data; | |
| 10231 | 254894 | value->data_len[i] = dfield->len; | |
| 10232 | 254894 | buf += sizeof(uint64_t); | |
| 10233 | } | ||
| 10234 | |||
| 10235 | 26278 | *valuep = value; | |
| 10236 | 26278 | } | |
| 10237 | |||
| 10238 | /** Handle the multi-value array, parse the values and store them | ||
| 10239 | @param[in] v JSON binary that has the mult-value | ||
| 10240 | @param[out] value store the parsed out value | ||
| 10241 | @param[in] fld array Field for the data | ||
| 10242 | @param[in] dfield InnoDB indexed field struct | ||
| 10243 | @param[in] comp if this is new InnoDB row type | ||
| 10244 | @param[in,out] heap heap memory | ||
| 10245 | @return true if values are valid and stored, otherwise false */ | ||
| 10246 | 26330 | static inline bool innobase_store_multi_value(json_binary::Value &v, | |
| 10247 | multi_value_data *value, | ||
| 10248 | Field_typed_array *fld, | ||
| 10249 | dfield_t *dfield, bool comp, | ||
| 10250 | mem_heap_t *heap) { | ||
| 10251 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26330 times.
|
26330 | if (v.type() == json_binary::Value::ERROR) { |
| 10252 | /* purecov: begin inspected */ | ||
| 10253 | ✗ | my_error(ER_INVALID_JSON_BINARY_DATA, MYF(0)); | |
| 10254 | ✗ | return (false); | |
| 10255 | /* purecov: end */ | ||
| 10256 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 26309 times.
|
26330 | } else if (v.type() == json_binary::Value::LITERAL_NULL) { |
| 10257 | /* When field is null, json parser creates LETERAL_NULL value. | ||
| 10258 | JSON NULL shouldn't get here in any other way */ | ||
| 10259 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | ut_ad(fld->is_null()); |
| 10260 | 21 | dfield_set_null(dfield); | |
| 10261 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 26278 times.
|
26309 | } else if (v.element_count() == 0) { |
| 10262 | 31 | dfield_set_data(dfield, nullptr, UNIV_NO_INDEX_VALUE); | |
| 10263 | } else { | ||
| 10264 | 26278 | innobase_store_multi_value_low(&v, &value, fld, dfield, comp, heap); | |
| 10265 | 26278 | dfield_set_data(dfield, value, UNIV_MULTI_VALUE_ARRAY_MARKER); | |
| 10266 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26278 times.
|
26278 | ut_ad(!value->duplicate()); |
| 10267 | } | ||
| 10268 | |||
| 10269 | 26330 | return (true); | |
| 10270 | } | ||
| 10271 | |||
| 10272 | /** Parse out multi-values from a MySQL record | ||
| 10273 | @param[in] mysql_table MySQL table structure | ||
| 10274 | @param[in] f_idx field index of the multi-value column | ||
| 10275 | @param[in,out] dfield field structure to store parsed multi-value | ||
| 10276 | @param[in,out] value nullptr or the multi-value structure | ||
| 10277 | to store the parsed values | ||
| 10278 | @param[in] old_val old value if exists | ||
| 10279 | @param[in] comp true if InnoDB table uses compact row format | ||
| 10280 | @param[in,out] heap memory heap */ | ||
| 10281 | 821 | void innobase_get_multi_value(const TABLE *mysql_table, ulint f_idx, | |
| 10282 | dfield_t *dfield, multi_value_data *value, | ||
| 10283 | uint old_val, ulint comp, mem_heap_t *heap) { | ||
| 10284 | Field_typed_array *fld; | ||
| 10285 | uint length; | ||
| 10286 | const char *ptr; | ||
| 10287 | |||
| 10288 |
2/4✓ Branch 0 taken 821 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 821 times.
|
821 | ut_ad(dfield_check_typed(dfield)); |
| 10289 | |||
| 10290 | 821 | fld = down_cast<Field_typed_array *>(mysql_table->field[f_idx]); | |
| 10291 | |||
| 10292 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 713 times.
|
821 | if (old_val) { |
| 10293 |
1/2✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
|
108 | length = fld->data_length(old_val); |
| 10294 |
1/2✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
|
108 | ptr = fld->get_binary(old_val); |
| 10295 | } else { | ||
| 10296 |
1/2✓ Branch 0 taken 713 times.
✗ Branch 1 not taken.
|
713 | length = fld->data_length(); |
| 10297 |
1/2✓ Branch 0 taken 713 times.
✗ Branch 1 not taken.
|
713 | ptr = fld->get_binary(); |
| 10298 | } | ||
| 10299 | |||
| 10300 |
1/2✓ Branch 0 taken 821 times.
✗ Branch 1 not taken.
|
821 | json_binary::Value v(json_binary::parse_binary(ptr, length)); |
| 10301 |
4/6✓ Branch 0 taken 21 times.
✓ Branch 1 taken 800 times.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 821 times.
|
821 | ut_ad(v.type() == json_binary::Value::ARRAY || |
| 10302 | v.type() == json_binary::Value::LITERAL_NULL); | ||
| 10303 | |||
| 10304 | ut_d(bool succ =) | ||
| 10305 |
1/2✓ Branch 0 taken 821 times.
✗ Branch 1 not taken.
|
821 | innobase_store_multi_value(v, value, fld, dfield, comp, heap); |
| 10306 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 821 times.
|
821 | ut_ad(succ); |
| 10307 | 821 | } | |
| 10308 | |||
| 10309 | #ifdef WITH_WSREP | ||
| 10310 | /* | ||
| 10311 | Check if replication should be done. It should be if: | ||
| 10312 | a. wsrep is enabled | ||
| 10313 | b. exec mode is local | ||
| 10314 | (it is workload executor node and not replicator node) | ||
| 10315 | c. No consistency check enforced. | ||
| 10316 | d. Ensure that bin-logging is enabled. | ||
| 10317 | Either mysql bin-logging or emulated bin logging. | ||
| 10318 | */ | ||
| 10319 | 79192160 | static bool wsrep_do_replication(THD *thd) { | |
| 10320 |
2/2✓ Branch 0 taken 4365752 times.
✓ Branch 1 taken 3135039 times.
|
86692951 | return wsrep_on(thd) && wsrep_thd_is_local(thd) && |
| 10321 |
3/4✓ Branch 0 taken 7500791 times.
✓ Branch 1 taken 71691434 times.
✓ Branch 2 taken 4365760 times.
✗ Branch 3 not taken.
|
91058768 | !wsrep_consistency_check(thd) && |
| 10322 |
2/2✓ Branch 0 taken 4358015 times.
✓ Branch 1 taken 7737 times.
|
83557977 | thd_binlog_format(thd) == BINLOG_FORMAT_ROW; |
| 10323 | } | ||
| 10324 | #endif /* WITH_WSREP */ | ||
| 10325 | |||
| 10326 | /** Stores a row in an InnoDB database, to the table specified in this | ||
| 10327 | handle. | ||
| 10328 | @return error code */ | ||
| 10329 | |||
| 10330 | 78850095 | int ha_innobase::write_row(uchar *record) /*!< in: a row in MySQL format */ | |
| 10331 | { | ||
| 10332 | dberr_t error; | ||
| 10333 | 78850095 | int error_result = 0; | |
| 10334 | 78850095 | bool auto_inc_used = false; | |
| 10335 | |||
| 10336 |
1/2✓ Branch 0 taken 78851552 times.
✗ Branch 1 not taken.
|
78850095 | DBUG_TRACE; |
| 10337 | |||
| 10338 | #ifdef WITH_WSREP | ||
| 10339 |
3/4✓ Branch 0 taken 75085647 times.
✓ Branch 1 taken 3765824 times.
✓ Branch 2 taken 75085821 times.
✗ Branch 3 not taken.
|
78851552 | DEBUG_SYNC(m_user_thd, "ha_innobase_write_row"); |
| 10340 | #endif /* WITH_WSREP */ | ||
| 10341 | |||
| 10342 | /* Increase the write count of handler */ | ||
| 10343 |
1/2✓ Branch 0 taken 78851504 times.
✗ Branch 1 not taken.
|
78851645 | ha_statistic_increment(&System_status_var::ha_write_count); |
| 10344 | |||
| 10345 |
3/4✓ Branch 0 taken 78851587 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13654241 times.
✓ Branch 3 taken 65197346 times.
|
78851504 | if (m_prebuilt->table->is_intrinsic()) { |
| 10346 |
1/2✓ Branch 0 taken 13654241 times.
✗ Branch 1 not taken.
|
13654241 | return intrinsic_table_write_row(record); |
| 10347 | } | ||
| 10348 | |||
| 10349 |
1/2✓ Branch 0 taken 65197253 times.
✗ Branch 1 not taken.
|
65197346 | trx_t *trx = thd_to_trx(m_user_thd); |
| 10350 | |||
| 10351 |
1/2✓ Branch 0 taken 65196143 times.
✗ Branch 1 not taken.
|
65197253 | TrxInInnoDB trx_in_innodb(trx); |
| 10352 | |||
| 10353 |
8/10✓ Branch 0 taken 65196848 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65196636 times.
✓ Branch 3 taken 212 times.
✓ Branch 4 taken 65196866 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 65196862 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 65197074 times.
|
65196143 | if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) { |
| 10354 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | innobase_rollback(ht, m_user_thd, false); |
| 10355 | |||
| 10356 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); |
| 10357 | } | ||
| 10358 | |||
| 10359 | /* Validation checks before we commence write_row operation. */ | ||
| 10360 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 65197043 times.
|
65197074 | if (high_level_read_only) { |
| 10361 |
2/4✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
|
31 | ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 10362 | 31 | return HA_ERR_TABLE_READONLY; | |
| 10363 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65197043 times.
|
65197043 | } else if (m_prebuilt->trx != trx) { |
| 10364 | ✗ | ib::error(ER_IB_MSG_558) << "The transaction object for the table handle is" | |
| 10365 | ✗ | " at " | |
| 10366 | ✗ | << static_cast<const void *>(m_prebuilt->trx) | |
| 10367 | ✗ | << ", but for the current thread it is at " | |
| 10368 | ✗ | << static_cast<const void *>(trx); | |
| 10369 | |||
| 10370 | ✗ | fputs("InnoDB: Dump of 200 bytes around m_prebuilt: ", stderr); | |
| 10371 | ✗ | ut_print_buf(stderr, ((const byte *)m_prebuilt) - 100, 200); | |
| 10372 | ✗ | fputs("\nInnoDB: Dump of 200 bytes around ha_data: ", stderr); | |
| 10373 | ✗ | ut_print_buf(stderr, ((const byte *)trx) - 100, 200); | |
| 10374 | ✗ | putc('\n', stderr); | |
| 10375 | ✗ | ut_error; | |
| 10376 |
3/4✓ Branch 0 taken 65196404 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2143883 times.
✓ Branch 3 taken 63052521 times.
|
65197043 | } else if (!trx_is_started(trx)) { |
| 10377 | 2143883 | ++trx->will_lock; | |
| 10378 | } | ||
| 10379 | |||
| 10380 | /* Handling of Auto-Increment Columns. */ | ||
| 10381 |
3/4✓ Branch 0 taken 14504589 times.
✓ Branch 1 taken 50691815 times.
✓ Branch 2 taken 14504622 times.
✗ Branch 3 not taken.
|
65196404 | if (table->next_number_field && record == table->record[0]) { |
| 10382 | /* Reset the error code before calling | ||
| 10383 | innobase_get_auto_increment(). */ | ||
| 10384 | 14504622 | m_prebuilt->autoinc_error = DB_SUCCESS; | |
| 10385 | |||
| 10386 |
1/2✓ Branch 0 taken 14504645 times.
✗ Branch 1 not taken.
|
14504622 | error_result = update_auto_increment(); |
| 10387 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 14504633 times.
|
14504645 | if (error_result) { |
| 10388 | /* We don't want to mask autoinc overflow errors. */ | ||
| 10389 | |||
| 10390 | /* Handle the case where the AUTOINC sub-system | ||
| 10391 | failed during initialization. */ | ||
| 10392 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (m_prebuilt->autoinc_error == DB_UNSUPPORTED) { |
| 10393 | ✗ | error_result = ER_AUTOINC_READ_FAILED; | |
| 10394 | /* Set the error message to report too. */ | ||
| 10395 | ✗ | my_error(ER_AUTOINC_READ_FAILED, MYF(0)); | |
| 10396 | ✗ | goto func_exit; | |
| 10397 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
|
12 | } else if (m_prebuilt->autoinc_error != DB_SUCCESS) { |
| 10398 | 1 | error = m_prebuilt->autoinc_error; | |
| 10399 | 1 | goto report_error; | |
| 10400 | } | ||
| 10401 | |||
| 10402 | /* MySQL errors are passed straight back. */ | ||
| 10403 | 11 | goto func_exit; | |
| 10404 | } | ||
| 10405 | |||
| 10406 | 14504633 | auto_inc_used = true; | |
| 10407 | } | ||
| 10408 | |||
| 10409 | /* Prepare INSERT graph that will be executed for actual INSERT | ||
| 10410 | (This is a one time operation) */ | ||
| 10411 |
2/2✓ Branch 0 taken 64923808 times.
✓ Branch 1 taken 272607 times.
|
65196415 | if (m_prebuilt->mysql_template == nullptr || |
| 10412 |
2/2✓ Branch 0 taken 725373 times.
✓ Branch 1 taken 64198435 times.
|
64923808 | m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) { |
| 10413 | /* Build the template used in converting quickly between | ||
| 10414 | the two database formats */ | ||
| 10415 | |||
| 10416 |
1/2✓ Branch 0 taken 997825 times.
✗ Branch 1 not taken.
|
997980 | build_template(true); |
| 10417 | } | ||
| 10418 | |||
| 10419 | #ifdef WITH_WSREP | ||
| 10420 | /* debug sync point has a special significance given the location | ||
| 10421 | where-in auto-inc value is generated but row insert action is not yet | ||
| 10422 | started. */ | ||
| 10423 |
3/4✓ Branch 0 taken 61435634 times.
✓ Branch 1 taken 3760790 times.
✓ Branch 2 taken 61436511 times.
✗ Branch 3 not taken.
|
65196260 | DEBUG_SYNC(m_user_thd, "pxc_autoinc_val_generated"); |
| 10424 | #endif /* WITH_WSREP */ | ||
| 10425 | |||
| 10426 |
1/2✓ Branch 0 taken 65196417 times.
✗ Branch 1 not taken.
|
65197301 | error = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 10427 | |||
| 10428 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65196417 times.
|
65196417 | if (error != DB_SUCCESS) { |
| 10429 | ✗ | goto report_error; | |
| 10430 | } | ||
| 10431 | |||
| 10432 | /* Execute insert graph that will result in actual insert. */ | ||
| 10433 |
1/2✓ Branch 0 taken 65197138 times.
✗ Branch 1 not taken.
|
65196417 | error = row_insert_for_mysql((byte *)record, m_prebuilt); |
| 10434 | |||
| 10435 |
3/4✓ Branch 0 taken 61436570 times.
✓ Branch 1 taken 3760828 times.
✓ Branch 2 taken 61436626 times.
✗ Branch 3 not taken.
|
65197138 | DEBUG_SYNC(m_user_thd, "ib_after_row_insert"); |
| 10436 | |||
| 10437 | /* Handling of errors related to auto-increment. */ | ||
| 10438 |
2/2✓ Branch 0 taken 14504774 times.
✓ Branch 1 taken 50692680 times.
|
65197454 | if (auto_inc_used) { |
| 10439 | ulonglong auto_inc; | ||
| 10440 | ulonglong col_max_value; | ||
| 10441 | |||
| 10442 | /* Note the number of rows processed for this statement, used | ||
| 10443 | by get_auto_increment() to determine the number of AUTO-INC | ||
| 10444 | values to reserve. This is only useful for a mult-value INSERT | ||
| 10445 | and is a statement level counter. */ | ||
| 10446 |
2/2✓ Branch 0 taken 13069054 times.
✓ Branch 1 taken 1435720 times.
|
14504774 | if (trx->n_autoinc_rows > 0) { |
| 10447 | 13069054 | --trx->n_autoinc_rows; | |
| 10448 | } | ||
| 10449 | |||
| 10450 | /* We need the upper limit of the col type to check for | ||
| 10451 | whether we update the table autoinc counter or not. */ | ||
| 10452 |
1/2✓ Branch 0 taken 14504774 times.
✗ Branch 1 not taken.
|
14504774 | col_max_value = table->next_number_field->get_max_int_value(); |
| 10453 | |||
| 10454 | /* Get the value that MySQL attempted to store in the table. */ | ||
| 10455 |
1/2✓ Branch 0 taken 14504774 times.
✗ Branch 1 not taken.
|
14504774 | auto_inc = table->next_number_field->val_int(); |
| 10456 | |||
| 10457 |
3/3✓ Branch 0 taken 258 times.
✓ Branch 1 taken 14504496 times.
✓ Branch 2 taken 20 times.
|
14504774 | switch (error) { |
| 10458 | 258 | case DB_DUPLICATE_KEY: | |
| 10459 | |||
| 10460 | /* A REPLACE command and LOAD DATA INFILE REPLACE | ||
| 10461 | handle a duplicate key error themselves, but we | ||
| 10462 | must update the autoinc counter if we are performing | ||
| 10463 | those statements. */ | ||
| 10464 | |||
| 10465 |
5/6✓ Branch 0 taken 258 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 98 times.
✓ Branch 4 taken 144 times.
✓ Branch 5 taken 10 times.
|
258 | switch (thd_sql_command(m_user_thd)) { |
| 10466 | 6 | case SQLCOM_LOAD: | |
| 10467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!m_prebuilt->allow_duplicates()) { |
| 10468 | ✗ | break; | |
| 10469 | } | ||
| 10470 | |||
| 10471 | case SQLCOM_REPLACE: | ||
| 10472 | case SQLCOM_INSERT_SELECT: | ||
| 10473 | case SQLCOM_REPLACE_SELECT: | ||
| 10474 | 104 | goto set_max_autoinc; | |
| 10475 | |||
| 10476 | #ifdef WITH_WSREP | ||
| 10477 | /* workaround for LP bug #355000, retrying the insert */ | ||
| 10478 | 144 | case SQLCOM_INSERT: { | |
| 10479 | const dict_index_t *err_index = | ||
| 10480 | 144 | trx_get_error_index(m_prebuilt->trx); | |
| 10481 |
1/30✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
144 | WSREP_DEBUG( |
| 10482 | "Found duplicate value for" | ||
| 10483 | " table (%s) - key (%s)" | ||
| 10484 | " THD %u, Auto-Inc-Value: %llu" | ||
| 10485 | " Offset: %llu, Increment: %llu", | ||
| 10486 | m_prebuilt->table->name.m_name, | ||
| 10487 | (err_index ? err_index->name() : "UNKNOWN"), | ||
| 10488 | wsrep_thd_thread_id(current_thd), auto_inc, | ||
| 10489 | m_prebuilt->autoinc_offset, m_prebuilt->autoinc_increment); | ||
| 10490 | |||
| 10491 |
1/2✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
|
144 | int mysql_key = get_dup_key(HA_ERR_FOUND_DUPP_KEY); |
| 10492 |
1/2✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
|
144 | KEY *key = (mysql_key < 0 || mysql_key == MAX_KEY) |
| 10493 |
1/2✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
|
144 | ? NULL |
| 10494 | 144 | : &table->key_info[mysql_key]; | |
| 10495 | |||
| 10496 | char key_buff[MAX_KEY_LENGTH]; | ||
| 10497 | 144 | String str(key_buff, sizeof(key_buff), system_charset_info); | |
| 10498 |
1/2✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
|
144 | key_unpack(&str, table, key); |
| 10499 |
1/26✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
144 | WSREP_DEBUG("Duplicate value: %s", str.c_ptr()); |
| 10500 | |||
| 10501 | 144 | break; | |
| 10502 | 144 | } | |
| 10503 | #endif /* WITH_WSREP */ | ||
| 10504 | |||
| 10505 | 10 | default: | |
| 10506 | 10 | break; | |
| 10507 | } | ||
| 10508 | |||
| 10509 | 154 | break; | |
| 10510 | |||
| 10511 | 14504496 | case DB_SUCCESS: | |
| 10512 | /* If the actual value inserted is greater than | ||
| 10513 | the upper limit of the interval, then we try and | ||
| 10514 | update the table upper limit. Note: last_value | ||
| 10515 | will be 0 if get_auto_increment() was not called. */ | ||
| 10516 | |||
| 10517 |
2/2✓ Branch 0 taken 1439216 times.
✓ Branch 1 taken 13065280 times.
|
14504496 | if (auto_inc >= m_prebuilt->autoinc_last_value) { |
| 10518 | 1439216 | set_max_autoinc: | |
| 10519 | /* This should filter out the negative | ||
| 10520 | values set explicitly by the user. */ | ||
| 10521 |
2/2✓ Branch 0 taken 1439090 times.
✓ Branch 1 taken 230 times.
|
1439320 | if (auto_inc <= col_max_value) { |
| 10522 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1439090 times.
|
1439090 | ut_a(m_prebuilt->autoinc_increment > 0); |
| 10523 | |||
| 10524 | ulonglong offset; | ||
| 10525 | ulonglong increment; | ||
| 10526 | dberr_t err; | ||
| 10527 | |||
| 10528 | #ifdef WITH_WSREP | ||
| 10529 | /* Applier threads which are processing ROW events and don't go | ||
| 10530 | through server level autoinc processing, therefore m_prebuilt | ||
| 10531 | autoinc values don't get properly assigned. Fetch values from | ||
| 10532 | server side. */ | ||
| 10533 |
9/12✓ Branch 0 taken 1439090 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1439090 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 675928 times.
✓ Branch 5 taken 763162 times.
✓ Branch 6 taken 675928 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 655772 times.
✓ Branch 9 taken 20156 times.
✓ Branch 10 taken 655772 times.
✓ Branch 11 taken 783318 times.
|
1439090 | if (wsrep_on(current_thd) && wsrep_thd_is_applying(m_user_thd)) { |
| 10534 |
2/4✓ Branch 0 taken 655772 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 655772 times.
✗ Branch 3 not taken.
|
655772 | wsrep_thd_auto_increment_variables(current_thd, &offset, |
| 10535 | &increment); | ||
| 10536 | } else { | ||
| 10537 | 783318 | offset = m_prebuilt->autoinc_offset; | |
| 10538 | 783318 | increment = m_prebuilt->autoinc_increment; | |
| 10539 | } | ||
| 10540 | #else | ||
| 10541 | offset = m_prebuilt->autoinc_offset; | ||
| 10542 | increment = m_prebuilt->autoinc_increment; | ||
| 10543 | #endif /* WITH_WSREP */ | ||
| 10544 | |||
| 10545 | #ifdef WITH_WSREP | ||
| 10546 | 1439090 | ulonglong prev_auto_inc = auto_inc; | |
| 10547 | #endif /* WITH_WSREP */ | ||
| 10548 | |||
| 10549 |
1/2✓ Branch 0 taken 1439090 times.
✗ Branch 1 not taken.
|
1439090 | auto_inc = innobase_next_autoinc(auto_inc, 1, increment, offset, |
| 10550 | col_max_value); | ||
| 10551 | |||
| 10552 | #ifdef WITH_WSREP | ||
| 10553 |
12/24✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1439088 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
1439090 | WSREP_DEBUG( |
| 10554 | "Generating new auto-inc" | ||
| 10555 | " next-value (Current: %llu," | ||
| 10556 | " New: %llu)", | ||
| 10557 | prev_auto_inc, auto_inc); | ||
| 10558 | #endif /* WITH_WSREP */ | ||
| 10559 | |||
| 10560 |
1/2✓ Branch 0 taken 1439089 times.
✗ Branch 1 not taken.
|
1439090 | err = innobase_set_max_autoinc(auto_inc); |
| 10561 | |||
| 10562 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1439089 times.
|
1439089 | if (err != DB_SUCCESS) { |
| 10563 | ✗ | error = err; | |
| 10564 | } | ||
| 10565 | } | ||
| 10566 | } | ||
| 10567 | 14504599 | break; | |
| 10568 | 20 | default: | |
| 10569 | 20 | break; | |
| 10570 | } | ||
| 10571 | } | ||
| 10572 | |||
| 10573 |
1/2✓ Branch 0 taken 65197118 times.
✗ Branch 1 not taken.
|
65197453 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 10574 | |||
| 10575 | 65197119 | report_error: | |
| 10576 | /* Cleanup and exit. */ | ||
| 10577 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 65197111 times.
|
65197119 | if (error == DB_TABLESPACE_DELETED) { |
| 10578 | 8 | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, | |
| 10579 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | table->s->table_name.str); |
| 10580 | } | ||
| 10581 | |||
| 10582 | error_result = | ||
| 10583 |
1/2✓ Branch 0 taken 65197136 times.
✗ Branch 1 not taken.
|
65197119 | convert_error_code_to_mysql(error, m_prebuilt->table->flags, m_user_thd); |
| 10584 | |||
| 10585 | #ifdef WITH_WSREP | ||
| 10586 | /* Append key | ||
| 10587 | a. there is no error in insert | ||
| 10588 | b. exec mode is local | ||
| 10589 | (it is workload executor node and not replicator node) | ||
| 10590 | c. wsrep is enabled | ||
| 10591 | d. No consistency check enforced. | ||
| 10592 | e. Ensure that bin-logging is enabled. | ||
| 10593 | Either mysql bin-logging or emulated bin logging. | ||
| 10594 | TODO: We allow replication even if binlog-format = STATEMENT. | ||
| 10595 | This is needed by pt-table-checksum. Now it is not a good idea | ||
| 10596 | to open this hook for pt-table-checksum but it exist like this for | ||
| 10597 | while now so to maintain compatibility we continue to provide it. | ||
| 10598 | With that there comes another existing dependency. | ||
| 10599 | Why not allow LDI operating with binlog-format = STATEMENT. | ||
| 10600 | There is no reason documented so will leave it as is for now. */ | ||
| 10601 |
7/8✓ Branch 0 taken 64272389 times.
✓ Branch 1 taken 924747 times.
✓ Branch 2 taken 64272690 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 62358392 times.
✓ Branch 5 taken 1914298 times.
✓ Branch 6 taken 61496651 times.
✓ Branch 7 taken 3700791 times.
|
127555533 | if (!error_result && (thd_sql_command(m_user_thd) != SQLCOM_CREATE_TABLE) && |
| 10602 |
3/4✓ Branch 0 taken 62358397 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3700791 times.
✓ Branch 3 taken 58657606 times.
|
62358392 | wsrep_do_replication(m_user_thd)) { |
| 10603 |
3/4✓ Branch 0 taken 3700791 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3700790 times.
|
3700791 | if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, record, |
| 10604 | NULL)) { | ||
| 10605 |
3/8✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
1 | DBUG_PRINT("wsrep", ("row key failed")); |
| 10606 | 1 | error_result = HA_ERR_INTERNAL_ERROR; | |
| 10607 | /* If we hit error during append key then we mark for complete | ||
| 10608 | transaction rollback */ | ||
| 10609 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | thd_mark_for_rollback(m_user_thd); |
| 10610 | 1 | goto wsrep_error; | |
| 10611 | } | ||
| 10612 | } | ||
| 10613 | 61496651 | wsrep_error: | |
| 10614 | #endif /* WITH_WSREP */ | ||
| 10615 | |||
| 10616 |
2/2✓ Branch 0 taken 65197441 times.
✓ Branch 1 taken 1 times.
|
65197442 | if (error_result == HA_FTS_INVALID_DOCID) { |
| 10617 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error(HA_FTS_INVALID_DOCID, MYF(0)); |
| 10618 | } | ||
| 10619 | |||
| 10620 | 65197441 | func_exit: | |
| 10621 | |||
| 10622 |
1/2✓ Branch 0 taken 65197392 times.
✗ Branch 1 not taken.
|
65197453 | innobase_active_small(); |
| 10623 | |||
| 10624 | 65197392 | return error_result; | |
| 10625 | 78851668 | } | |
| 10626 | |||
| 10627 | #ifdef WITH_WSREP | ||
| 10628 | #include <openssl/md5.h> | ||
| 10629 | |||
| 10630 | 1640278 | static int wsrep_calc_row_hash(byte *digest, const uchar *row, TABLE *table, | |
| 10631 | row_prebuilt_t *prebuilt, THD *thd) { | ||
| 10632 | Field *field; | ||
| 10633 | enum_field_types field_mysql_type; | ||
| 10634 | uint n_fields; | ||
| 10635 | ulint len; | ||
| 10636 | const byte *ptr; | ||
| 10637 | ulint col_type; | ||
| 10638 | uint i; | ||
| 10639 | |||
| 10640 |
1/2✓ Branch 0 taken 1640278 times.
✗ Branch 1 not taken.
|
1640278 | void *ctx = wsrep_md5_init(); |
| 10641 | |||
| 10642 | 1640278 | n_fields = table->s->fields; | |
| 10643 | |||
| 10644 |
2/2✓ Branch 0 taken 1645803 times.
✓ Branch 1 taken 1640278 times.
|
3286081 | for (i = 0; i < n_fields; i++) { |
| 10645 | 1645803 | byte null_byte = 0; | |
| 10646 | 1645803 | byte true_byte = 1; | |
| 10647 | |||
| 10648 | 1645803 | field = table->field[i]; | |
| 10649 | |||
| 10650 | 1645803 | ptr = (const byte *)row + get_field_offset(table, field); | |
| 10651 |
1/2✓ Branch 0 taken 1645803 times.
✗ Branch 1 not taken.
|
1645803 | len = field->pack_length(); |
| 10652 | |||
| 10653 |
1/2✓ Branch 0 taken 1645803 times.
✗ Branch 1 not taken.
|
1645803 | field_mysql_type = field->type(); |
| 10654 | |||
| 10655 | /* Get corresponding InnoDB type */ | ||
| 10656 | ulint unsigned_flag; | ||
| 10657 |
1/2✓ Branch 0 taken 1645803 times.
✗ Branch 1 not taken.
|
1645803 | col_type = get_innobase_type_from_mysql_type(&unsigned_flag, field); |
| 10658 | |||
| 10659 |
3/3✓ Branch 0 taken 26 times.
✓ Branch 1 taken 1013163 times.
✓ Branch 2 taken 632614 times.
|
1645803 | switch (col_type) { |
| 10660 | 26 | case DATA_BLOB: | |
| 10661 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | ptr = row_mysql_read_blob_ref(&len, ptr, len, false, 0, 0, |
| 10662 | &prebuilt->compress_heap); | ||
| 10663 | 26 | break; | |
| 10664 | |||
| 10665 | 1013163 | case DATA_VARCHAR: | |
| 10666 | case DATA_BINARY: | ||
| 10667 | case DATA_VARMYSQL: | ||
| 10668 |
1/2✓ Branch 0 taken 1013163 times.
✗ Branch 1 not taken.
|
1013163 | if (field_mysql_type == MYSQL_TYPE_VARCHAR) { |
| 10669 | /* This is a >= 5.0.3 type true VARCHAR where | ||
| 10670 | the real payload data length is stored in | ||
| 10671 | 1 or 2 bytes */ | ||
| 10672 | |||
| 10673 | 1013163 | ptr = row_mysql_read_true_varchar( | |
| 10674 | &len, ptr, | ||
| 10675 |
2/4✓ Branch 0 taken 1013163 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1013163 times.
✗ Branch 3 not taken.
|
1013163 | (ulint)(((Field_varstring *)field)->get_length_bytes())); |
| 10676 | } | ||
| 10677 | |||
| 10678 | 1013163 | break; | |
| 10679 | 632614 | default: | |
| 10680 | 632614 | break; | |
| 10681 | } | ||
| 10682 | |||
| 10683 |
3/4✓ Branch 0 taken 1645803 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✓ Branch 3 taken 1645677 times.
|
1645803 | if (field->is_null_in_record(row)) { |
| 10684 |
1/2✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
|
126 | wsrep_md5_update(ctx, (char *)&null_byte, 1); |
| 10685 | } else { | ||
| 10686 |
1/2✓ Branch 0 taken 1645677 times.
✗ Branch 1 not taken.
|
1645677 | wsrep_md5_update(ctx, (char *)&true_byte, 1); |
| 10687 |
1/2✓ Branch 0 taken 1645677 times.
✗ Branch 1 not taken.
|
1645677 | wsrep_md5_update(ctx, (char *)ptr, len); |
| 10688 | } | ||
| 10689 | } | ||
| 10690 |
1/2✓ Branch 0 taken 1640278 times.
✗ Branch 1 not taken.
|
1640278 | wsrep_compute_md5_hash(digest, ctx); |
| 10691 | 1640278 | return (0); | |
| 10692 | } | ||
| 10693 | #endif /* WITH_WSREP */ | ||
| 10694 | |||
| 10695 | /** Fill the update vector's "old_vrow" field for those non-updated, | ||
| 10696 | but indexed columns. Such columns could stil present in the virtual | ||
| 10697 | index rec fields even if they are not updated (some other fields updated), | ||
| 10698 | so needs to be logged. | ||
| 10699 | @param[in] prebuilt InnoDB prebuilt struct | ||
| 10700 | @param[in,out] vfield field to filled | ||
| 10701 | @param[in] o_len actual column length | ||
| 10702 | @param[in] old_mysql_row_col MySQL old field ptr | ||
| 10703 | @param[in] col_pack_len MySQL field col length | ||
| 10704 | @param[in,out] buf buffer for a converted integer value | ||
| 10705 | @return used buffer ptr from row_mysql_store_col_in_innobase_format() */ | ||
| 10706 | 1225 | static byte *innodb_fill_old_vcol_val(row_prebuilt_t *prebuilt, | |
| 10707 | dfield_t *vfield, ulint o_len, | ||
| 10708 | const byte *old_mysql_row_col, | ||
| 10709 | ulint col_pack_len, byte *buf) { | ||
| 10710 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1225 times.
|
1225 | ut_ad(dfield_check_typed(vfield)); |
| 10711 | |||
| 10712 |
2/2✓ Branch 0 taken 1209 times.
✓ Branch 1 taken 16 times.
|
1225 | if (o_len != UNIV_SQL_NULL) { |
| 10713 | 1209 | buf = row_mysql_store_col_in_innobase_format( | |
| 10714 | vfield, buf, true, old_mysql_row_col, col_pack_len, | ||
| 10715 | 1209 | dict_table_is_comp(prebuilt->table), false, nullptr, 0, nullptr); | |
| 10716 | } else { | ||
| 10717 | 16 | dfield_set_null(vfield); | |
| 10718 | } | ||
| 10719 | |||
| 10720 | 1225 | return (buf); | |
| 10721 | } | ||
| 10722 | |||
| 10723 | /** Parse out multi-values from both old and new MySQL records, | ||
| 10724 | at the meantime, calculate the difference between two records. | ||
| 10725 | @param[in] mysql_table MySQL table structure | ||
| 10726 | @param[in] field_idx field index of the multi-value column | ||
| 10727 | @param[in,out] old_field field structure to store the parsed old value | ||
| 10728 | @param[in,out] new_field field structure to store the parsed new value | ||
| 10729 | @param[in] old_value old value to parse | ||
| 10730 | @param[in] comp true if InnoDB table uses compact row format | ||
| 10731 | @param[in,out] heap memory heap */ | ||
| 10732 | 85 | static void innobase_get_multi_value_and_diff( | |
| 10733 | const TABLE *mysql_table, ulint field_idx, dfield_t *old_field, | ||
| 10734 | dfield_t *new_field, uint old_value, ulint comp, mem_heap_t *heap) { | ||
| 10735 | Field_typed_array *fld; | ||
| 10736 | 85 | const char *old_ptr = nullptr; | |
| 10737 | 85 | const char *new_ptr = nullptr; | |
| 10738 | uint old_len; | ||
| 10739 | uint new_len; | ||
| 10740 | |||
| 10741 | 85 | fld = down_cast<Field_typed_array *>(mysql_table->field[field_idx]); | |
| 10742 | |||
| 10743 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | old_ptr = fld->get_binary(old_value); |
| 10744 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | old_len = fld->get_length(old_value); |
| 10745 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | new_ptr = fld->get_binary(); |
| 10746 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | new_len = fld->get_length(); |
| 10747 | |||
| 10748 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | json_binary::Value old_v(json_binary::parse_binary(old_ptr, old_len)); |
| 10749 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | json_binary::Value new_v(json_binary::parse_binary(new_ptr, new_len)); |
| 10750 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | ut_ad(old_v.type() == json_binary::Value::ARRAY); |
| 10751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | ut_ad(new_v.type() == json_binary::Value::ARRAY); |
| 10752 | |||
| 10753 | ut_d(bool succ1 =) | ||
| 10754 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | innobase_store_multi_value(old_v, nullptr, fld, old_field, comp, heap); |
| 10755 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | ut_ad(succ1); |
| 10756 | ut_d(bool succ2 =) | ||
| 10757 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | innobase_store_multi_value(new_v, nullptr, fld, new_field, comp, heap); |
| 10758 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | ut_ad(succ2); |
| 10759 | |||
| 10760 |
2/4✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 85 times.
|
85 | ut_ad(!dfield_is_null(old_field)); |
| 10761 |
2/4✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 85 times.
|
85 | ut_ad(!dfield_is_null(new_field)); |
| 10762 | /* If no indexed value, then no need to get the difference */ | ||
| 10763 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | if (old_field->len == UNIV_NO_INDEX_VALUE || |
| 10764 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | new_field->len == UNIV_NO_INDEX_VALUE) { |
| 10765 | ✗ | return; | |
| 10766 | } | ||
| 10767 | |||
| 10768 | /* Now old_field and new_field are having both multi-value data, in the | ||
| 10769 | same sequence with data in old_v and new_v, which are also sorted in | ||
| 10770 | ascending order. */ | ||
| 10771 | |||
| 10772 | 85 | uint old_counter = 0; | |
| 10773 | 85 | uint new_counter = 0; | |
| 10774 | 85 | multi_value_data *old_mv = static_cast<multi_value_data *>(old_field->data); | |
| 10775 | 85 | multi_value_data *new_mv = static_cast<multi_value_data *>(new_field->data); | |
| 10776 | |||
| 10777 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | old_mv->alloc_bitset(heap); |
| 10778 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | new_mv->alloc_bitset(heap); |
| 10779 | |||
| 10780 |
6/6✓ Branch 0 taken 294 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 285 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 285 times.
✓ Branch 5 taken 85 times.
|
664 | while (old_counter < old_v.element_count() && |
| 10781 | 294 | new_counter < new_v.element_count()) { | |
| 10782 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
|
285 | ut_ad(old_counter < old_mv->num_v); |
| 10783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
|
285 | ut_ad(new_counter < new_mv->num_v); |
| 10784 | |||
| 10785 |
3/6✓ Branch 0 taken 285 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 285 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 285 times.
✗ Branch 5 not taken.
|
285 | int res = old_v.element(old_counter).eq(new_v.element(new_counter)); |
| 10786 |
2/2✓ Branch 0 taken 82 times.
✓ Branch 1 taken 203 times.
|
285 | if (res == 0) { |
| 10787 |
1/2✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
|
82 | old_mv->bitset->set(old_counter++, false); |
| 10788 |
1/2✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
|
82 | new_mv->bitset->set(new_counter++, false); |
| 10789 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 35 times.
|
203 | } else if (res < 0) { |
| 10790 | 168 | ++old_counter; | |
| 10791 | } else { | ||
| 10792 | 35 | ++new_counter; | |
| 10793 | } | ||
| 10794 | } | ||
| 10795 | } | ||
| 10796 | |||
| 10797 | /** Checks which fields have changed in a row and stores information | ||
| 10798 | of them to an update vector. | ||
| 10799 | @return DB_SUCCESS or error code */ | ||
| 10800 | 14643831 | static dberr_t calc_row_difference( | |
| 10801 | upd_t *uvect, /*!< in/out: update vector */ | ||
| 10802 | const uchar *old_row, /*!< in: old row in MySQL format */ | ||
| 10803 | uchar *new_row, /*!< in: new row in MySQL format */ | ||
| 10804 | TABLE *table, /*!< in: table in MySQL data | ||
| 10805 | dictionary */ | ||
| 10806 | uchar *upd_buff, /*!< in: buffer to use */ | ||
| 10807 | ulint buff_len, /*!< in: buffer length */ | ||
| 10808 | row_prebuilt_t *prebuilt, /*!< in: InnoDB prebuilt struct */ | ||
| 10809 | THD *thd) /*!< in: user thread */ | ||
| 10810 | { | ||
| 10811 | 14643831 | uchar *original_upd_buff = upd_buff; | |
| 10812 | Field *field; | ||
| 10813 | enum_field_types field_mysql_type; | ||
| 10814 | uint n_fields; | ||
| 10815 | ulint o_len; | ||
| 10816 | ulint n_len; | ||
| 10817 | ulint col_pack_len; | ||
| 10818 | const byte *new_mysql_row_col; | ||
| 10819 | const byte *old_mysql_row_col; | ||
| 10820 | const byte *o_ptr; | ||
| 10821 | const byte *n_ptr; | ||
| 10822 | byte *buf; | ||
| 10823 | upd_field_t *ufield; | ||
| 10824 | ulint col_type; | ||
| 10825 | 14643831 | ulint n_changed = 0; | |
| 10826 | 14643831 | dfield_t dfield; | |
| 10827 | dict_index_t *clust_index; | ||
| 10828 | uint i; | ||
| 10829 | 14643846 | bool changes_fts_column = false; | |
| 10830 | 14643846 | bool changes_fts_doc_col = false; | |
| 10831 |
1/2✓ Branch 0 taken 14643849 times.
✗ Branch 1 not taken.
|
14643846 | trx_t *trx = thd_to_trx(thd); |
| 10832 | 14643849 | doc_id_t doc_id = FTS_NULL_DOC_ID; | |
| 10833 | 14643849 | ulint comp = 0; | |
| 10834 | 14643849 | ulint num_v = 0; | |
| 10835 | |||
| 10836 |
5/8✓ Branch 0 taken 4 times.
✓ Branch 1 taken 14643845 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 14643851 times.
|
14643849 | ut_ad(!srv_read_only_mode || prebuilt->table->is_intrinsic()); |
| 10837 | |||
| 10838 |
1/2✓ Branch 0 taken 14643838 times.
✗ Branch 1 not taken.
|
14643851 | comp = dict_table_is_comp(prebuilt->table); |
| 10839 | |||
| 10840 | 14643838 | n_fields = table->s->fields; | |
| 10841 |
1/2✓ Branch 0 taken 14643845 times.
✗ Branch 1 not taken.
|
14643838 | clust_index = prebuilt->table->first_index(); |
| 10842 | |||
| 10843 | /* We use upd_buff to convert changed fields */ | ||
| 10844 | 14643845 | buf = (byte *)upd_buff; | |
| 10845 | |||
| 10846 |
2/2✓ Branch 0 taken 147578907 times.
✓ Branch 1 taken 14643871 times.
|
162222778 | for (i = 0; i < n_fields; i++) { |
| 10847 | 147578907 | dfield.reset(); | |
| 10848 | |||
| 10849 | 147578961 | field = table->field[i]; | |
| 10850 |
4/4✓ Branch 0 taken 316102 times.
✓ Branch 1 taken 147262859 times.
✓ Branch 2 taken 166284 times.
✓ Branch 3 taken 149818 times.
|
147578961 | bool is_virtual = innobase_is_v_fld(field); |
| 10851 |
1/2✓ Branch 0 taken 147578942 times.
✗ Branch 1 not taken.
|
147578961 | bool is_multi_value = innobase_is_multi_value_fld(field); |
| 10852 | dict_col_t *col; | ||
| 10853 | |||
| 10854 |
2/2✓ Branch 0 taken 166284 times.
✓ Branch 1 taken 147412658 times.
|
147578942 | if (is_virtual) { |
| 10855 | 166284 | col = &prebuilt->table->v_cols[num_v].m_col; | |
| 10856 | } else { | ||
| 10857 | 147412658 | col = &prebuilt->table->cols[i - num_v]; | |
| 10858 | } | ||
| 10859 | |||
| 10860 | 147578942 | o_ptr = (const byte *)old_row + get_field_offset(table, field); | |
| 10861 | 147578945 | n_ptr = (const byte *)new_row + get_field_offset(table, field); | |
| 10862 | |||
| 10863 | /* Use new_mysql_row_col and col_pack_len save the values */ | ||
| 10864 | |||
| 10865 | 147578883 | new_mysql_row_col = n_ptr; | |
| 10866 | 147578883 | old_mysql_row_col = o_ptr; | |
| 10867 |
1/2✓ Branch 0 taken 147578843 times.
✗ Branch 1 not taken.
|
147578883 | col_pack_len = field->pack_length(); |
| 10868 | |||
| 10869 | 147578843 | o_len = col_pack_len; | |
| 10870 | 147578843 | n_len = col_pack_len; | |
| 10871 | |||
| 10872 | /* We use o_ptr and n_ptr to dig up the actual data for | ||
| 10873 | comparison. */ | ||
| 10874 | |||
| 10875 |
1/2✓ Branch 0 taken 147578863 times.
✗ Branch 1 not taken.
|
147578843 | field_mysql_type = field->type(); |
| 10876 | |||
| 10877 | 147578863 | col_type = col->mtype; | |
| 10878 | |||
| 10879 | /* Reset the type to BLOB for multi-value field, since server may | ||
| 10880 | keep it as non-BLOB one. */ | ||
| 10881 |
2/2✓ Branch 0 taken 201 times.
✓ Branch 1 taken 147578662 times.
|
147578863 | if (is_multi_value) { |
| 10882 | 201 | col_type = DATA_BLOB; | |
| 10883 | } | ||
| 10884 | |||
| 10885 |
3/3✓ Branch 0 taken 30520499 times.
✓ Branch 1 taken 18926659 times.
✓ Branch 2 taken 98131705 times.
|
147578863 | switch (col_type) { |
| 10886 | 30520499 | case DATA_BLOB: | |
| 10887 | case DATA_POINT: | ||
| 10888 | case DATA_VAR_POINT: | ||
| 10889 | case DATA_GEOMETRY: | ||
| 10890 | /* Do not compress blob column while comparing */ | ||
| 10891 |
1/2✓ Branch 0 taken 30520511 times.
✗ Branch 1 not taken.
|
30520499 | o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len, false, nullptr, 0, |
| 10892 | &prebuilt->compress_heap); | ||
| 10893 |
1/2✓ Branch 0 taken 30520506 times.
✗ Branch 1 not taken.
|
30520511 | n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len, false, nullptr, 0, |
| 10894 | &prebuilt->compress_heap); | ||
| 10895 | |||
| 10896 | 30520506 | break; | |
| 10897 | |||
| 10898 | 18926659 | case DATA_VARCHAR: | |
| 10899 | case DATA_BINARY: | ||
| 10900 | case DATA_VARMYSQL: | ||
| 10901 |
1/2✓ Branch 0 taken 18926661 times.
✗ Branch 1 not taken.
|
18926659 | if (field_mysql_type == MYSQL_TYPE_VARCHAR) { |
| 10902 | /* This is a >= 5.0.3 type true VARCHAR where | ||
| 10903 | the real payload data length is stored in | ||
| 10904 | 1 or 2 bytes */ | ||
| 10905 | |||
| 10906 | 37853307 | o_ptr = row_mysql_read_true_varchar(&o_len, o_ptr, | |
| 10907 |
2/4✓ Branch 0 taken 18926654 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18926653 times.
✗ Branch 3 not taken.
|
18926661 | (ulint)field->get_length_bytes()); |
| 10908 | |||
| 10909 | 18926664 | n_ptr = row_mysql_read_true_varchar(&n_len, n_ptr, | |
| 10910 |
2/4✓ Branch 0 taken 18926659 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18926664 times.
✗ Branch 3 not taken.
|
18926653 | (ulint)field->get_length_bytes()); |
| 10911 | } | ||
| 10912 | |||
| 10913 | 18926662 | break; | |
| 10914 | 147578873 | default:; | |
| 10915 | } | ||
| 10916 | |||
| 10917 |
6/6✓ Branch 0 taken 25419321 times.
✓ Branch 1 taken 122159552 times.
✓ Branch 2 taken 305 times.
✓ Branch 3 taken 25419016 times.
✓ Branch 4 taken 305 times.
✓ Branch 5 taken 147578568 times.
|
147579178 | if (field_mysql_type == MYSQL_TYPE_LONGLONG && prebuilt->table->fts && |
| 10918 |
2/4✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 305 times.
✗ Branch 3 not taken.
|
305 | innobase_strcasecmp(field->field_name, FTS_DOC_ID_COL_NAME) == 0) { |
| 10919 |
1/2✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
|
305 | doc_id = (doc_id_t)mach_read_from_n_little_endian(n_ptr, 8); |
| 10920 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
|
305 | if (doc_id == 0) { |
| 10921 | ✗ | return (DB_FTS_INVALID_DOCID); | |
| 10922 | } | ||
| 10923 | } | ||
| 10924 | |||
| 10925 |
2/2✓ Branch 0 taken 75611001 times.
✓ Branch 1 taken 71967929 times.
|
147578873 | if (field->is_nullable()) { |
| 10926 |
3/4✓ Branch 0 taken 75610995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35965207 times.
✓ Branch 3 taken 39645788 times.
|
75611001 | if (field->is_null_in_record(old_row)) { |
| 10927 | 35965207 | o_len = UNIV_SQL_NULL; | |
| 10928 | } | ||
| 10929 | |||
| 10930 |
3/4✓ Branch 0 taken 75610985 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34548052 times.
✓ Branch 3 taken 41062933 times.
|
75610995 | if (field->is_null_in_record(new_row)) { |
| 10931 | 34548052 | n_len = UNIV_SQL_NULL; | |
| 10932 | } | ||
| 10933 | } | ||
| 10934 | |||
| 10935 | #ifdef UNIV_DEBUG | ||
| 10936 | 147578914 | bool online_ord_part = false; | |
| 10937 | #endif | ||
| 10938 | |||
| 10939 |
2/2✓ Branch 0 taken 166284 times.
✓ Branch 1 taken 147412630 times.
|
147578914 | if (is_virtual) { |
| 10940 | /* If the virtual column is not indexed, | ||
| 10941 | we shall ignore it for update */ | ||
| 10942 |
2/2✓ Branch 0 taken 159692 times.
✓ Branch 1 taken 6592 times.
|
166284 | if (!col->ord_part) { |
| 10943 | /* Check whether there is a table-rebuilding | ||
| 10944 | online ALTER TABLE in progress, and this | ||
| 10945 | virtual column could be newly indexed, thus | ||
| 10946 | it will be materialized. Then we will have | ||
| 10947 | to log its update. | ||
| 10948 | Note, we do not support online dropping virtual | ||
| 10949 | column while adding new index, nor with | ||
| 10950 | online alter column order while adding index, | ||
| 10951 | so the virtual column sequence must not change | ||
| 10952 | if it is online operation */ | ||
| 10953 |
5/6✓ Branch 0 taken 159692 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 159687 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 159691 times.
|
159697 | if (dict_index_is_online_ddl(clust_index) && |
| 10954 |
3/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
|
5 | row_log_col_is_indexed(clust_index, num_v)) { |
| 10955 | #ifdef UNIV_DEBUG | ||
| 10956 | 1 | online_ord_part = true; | |
| 10957 | #endif | ||
| 10958 | } else { | ||
| 10959 | 159691 | num_v++; | |
| 10960 | 159691 | continue; | |
| 10961 | } | ||
| 10962 | } | ||
| 10963 | |||
| 10964 |
2/2✓ Branch 0 taken 216 times.
✓ Branch 1 taken 6377 times.
|
6593 | if (!uvect->old_vrow) { |
| 10965 | 216 | uvect->old_vrow = | |
| 10966 |
1/2✓ Branch 0 taken 216 times.
✗ Branch 1 not taken.
|
216 | dtuple_create_with_vcol(uvect->heap, 0, prebuilt->table->n_v_cols); |
| 10967 |
2/2✓ Branch 0 taken 364 times.
✓ Branch 1 taken 216 times.
|
580 | for (uint j = 0; j < prebuilt->table->n_v_cols; j++) { |
| 10968 |
1/2✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
|
364 | dfield_t *field = dtuple_get_nth_v_field(uvect->old_vrow, j); |
| 10969 | /* In case a multi-value field checking read uninitialized value */ | ||
| 10970 |
1/2✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
|
364 | dfield_get_type(field)->prtype = 0; |
| 10971 |
1/2✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
|
364 | dfield_set_len(field, UNIV_SQL_NULL); |
| 10972 | } | ||
| 10973 | } | ||
| 10974 | |||
| 10975 |
2/2✓ Branch 0 taken 5785 times.
✓ Branch 1 taken 808 times.
|
6593 | ulint max_field_len = DICT_MAX_FIELD_LEN_BY_FORMAT(prebuilt->table); |
| 10976 | |||
| 10977 | /* for virtual columns, we only materialize | ||
| 10978 | its index, and index field length would not | ||
| 10979 | exceed max_field_len. So continue if the | ||
| 10980 | first max_field_len bytes are matched up */ | ||
| 10981 |
4/4✓ Branch 0 taken 6540 times.
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 6509 times.
✓ Branch 3 taken 31 times.
|
6593 | if (o_len != UNIV_SQL_NULL && n_len != UNIV_SQL_NULL && |
| 10982 |
3/4✓ Branch 0 taken 1608 times.
✓ Branch 1 taken 4901 times.
✓ Branch 2 taken 1608 times.
✗ Branch 3 not taken.
|
6509 | o_len >= max_field_len && n_len >= max_field_len && |
| 10983 |
2/2✓ Branch 0 taken 606 times.
✓ Branch 1 taken 1002 times.
|
1608 | memcmp(o_ptr, n_ptr, max_field_len) == 0) { |
| 10984 |
1/2✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
|
606 | dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v); |
| 10985 |
2/4✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 606 times.
✗ Branch 3 not taken.
|
606 | col->copy_type(dfield_get_type(vfield)); |
| 10986 | |||
| 10987 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 606 times.
|
606 | if (is_multi_value) { |
| 10988 | ✗ | innobase_get_multi_value(prebuilt->m_mysql_table, i, vfield, nullptr, | |
| 10989 | ✗ | static_cast<uint>(old_row - new_row), comp, | |
| 10990 | uvect->per_stmt_heap); | ||
| 10991 | } else { | ||
| 10992 |
1/2✓ Branch 0 taken 606 times.
✗ Branch 1 not taken.
|
606 | buf = innodb_fill_old_vcol_val(prebuilt, vfield, o_len, |
| 10993 | old_mysql_row_col, col_pack_len, buf); | ||
| 10994 | } | ||
| 10995 | 606 | num_v++; | |
| 10996 | 606 | continue; | |
| 10997 | 606 | } | |
| 10998 | } | ||
| 10999 | |||
| 11000 |
6/6✓ Branch 0 taken 145327803 times.
✓ Branch 1 taken 2090814 times.
✓ Branch 2 taken 110933312 times.
✓ Branch 3 taken 34394491 times.
✓ Branch 4 taken 106484623 times.
✓ Branch 5 taken 4448689 times.
|
147418617 | if (o_len != n_len || (o_len != UNIV_SQL_NULL && o_len != 0 && |
| 11001 |
2/2✓ Branch 0 taken 7170946 times.
✓ Branch 1 taken 99313677 times.
|
106484623 | 0 != memcmp(o_ptr, n_ptr, o_len))) { |
| 11002 | /* The field has changed */ | ||
| 11003 | 9261760 | bool multi_value_calc_by_diff = false; | |
| 11004 | 9261760 | dfield_t old_field, new_field; | |
| 11005 | |||
| 11006 | 9261790 | ufield = uvect->fields + n_changed; | |
| 11007 | |||
| 11008 | 9261790 | const auto old_old_v_val = ufield->old_v_val; | |
| 11009 | |||
| 11010 | UNIV_MEM_INVALID(ufield, sizeof *ufield); | ||
| 11011 | |||
| 11012 | /* Let us use a dummy dfield to make the conversion | ||
| 11013 | from the MySQL column format to the InnoDB format */ | ||
| 11014 | |||
| 11015 | /* If the length of new geometry object is 0, means | ||
| 11016 | this object is invalid geometry object, we need | ||
| 11017 | to block it. */ | ||
| 11018 |
5/8✓ Branch 0 taken 3248 times.
✓ Branch 1 taken 9258547 times.
✓ Branch 2 taken 3248 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3248 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9261795 times.
|
9261790 | if (DATA_GEOMETRY_MTYPE(col_type) && o_len != 0 && n_len == 0) { |
| 11019 | ✗ | return (DB_CANT_CREATE_GEOMETRY_OBJECT); | |
| 11020 | } | ||
| 11021 | |||
| 11022 |
6/6✓ Branch 0 taken 112 times.
✓ Branch 1 taken 9261683 times.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 85 times.
✓ Branch 5 taken 9261710 times.
|
9261888 | if (is_multi_value && n_len != UNIV_SQL_NULL && |
| 11023 |
3/4✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 8 times.
|
93 | !field->is_null_in_record(old_row)) { |
| 11024 | /* Multi-value field and both old and new are not NULL, | ||
| 11025 | parse the value separately and also calculate the difference */ | ||
| 11026 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | ut_ad(is_virtual); |
| 11027 | |||
| 11028 |
2/4✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✗ Branch 3 not taken.
|
85 | col->copy_type(dfield_get_type(&old_field)); |
| 11029 |
2/4✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✗ Branch 3 not taken.
|
85 | col->copy_type(dfield_get_type(&new_field)); |
| 11030 | |||
| 11031 | 85 | innobase_get_multi_value_and_diff( | |
| 11032 | 85 | prebuilt->m_mysql_table, i, &old_field, &new_field, | |
| 11033 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | static_cast<uint>(old_row - new_row), comp, uvect->per_stmt_heap); |
| 11034 | |||
| 11035 | 85 | multi_value_calc_by_diff = true; | |
| 11036 | } | ||
| 11037 | |||
| 11038 |
2/2✓ Branch 0 taken 9239333 times.
✓ Branch 1 taken 22462 times.
|
9261795 | if (n_len != UNIV_SQL_NULL) { |
| 11039 |
2/4✓ Branch 0 taken 9239324 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9239322 times.
✗ Branch 3 not taken.
|
9239333 | col->copy_type(dfield_get_type(&dfield)); |
| 11040 | |||
| 11041 |
4/4✓ Branch 0 taken 93 times.
✓ Branch 1 taken 9239229 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 85 times.
|
9239322 | if (is_multi_value && !multi_value_calc_by_diff) { |
| 11042 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | innobase_get_multi_value(prebuilt->m_mysql_table, i, &dfield, nullptr, |
| 11043 | 0, comp, uvect->per_stmt_heap); | ||
| 11044 | } else { | ||
| 11045 |
1/2✓ Branch 0 taken 9239302 times.
✗ Branch 1 not taken.
|
9239311 | buf = row_mysql_store_col_in_innobase_format( |
| 11046 | &dfield, (byte *)buf, true, new_mysql_row_col, col_pack_len, comp, | ||
| 11047 | 9239314 | field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED, | |
| 11048 | 9239314 | reinterpret_cast<const byte *>(field->zip_dict_data.str), | |
| 11049 | field->zip_dict_data.length, &prebuilt->compress_heap); | ||
| 11050 | } | ||
| 11051 | |||
| 11052 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 9239225 times.
|
9239310 | if (multi_value_calc_by_diff) { |
| 11053 | 85 | dfield_copy(&ufield->new_val, &new_field); | |
| 11054 | } else { | ||
| 11055 | 9239225 | dfield_copy(&ufield->new_val, &dfield); | |
| 11056 | } | ||
| 11057 | } else { | ||
| 11058 |
2/4✓ Branch 0 taken 22456 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22456 times.
✗ Branch 3 not taken.
|
22462 | col->copy_type(dfield_get_type(&ufield->new_val)); |
| 11059 |
1/2✓ Branch 0 taken 22453 times.
✗ Branch 1 not taken.
|
22456 | dfield_set_null(&ufield->new_val); |
| 11060 | } | ||
| 11061 | |||
| 11062 | 9261757 | ufield->exp = nullptr; | |
| 11063 | 9261757 | ufield->orig_len = 0; | |
| 11064 | 9261757 | ufield->mysql_field = field; | |
| 11065 | |||
| 11066 |
2/2✓ Branch 0 taken 5279 times.
✓ Branch 1 taken 9256478 times.
|
9261757 | if (is_virtual) { |
| 11067 |
1/2✓ Branch 0 taken 5279 times.
✗ Branch 1 not taken.
|
5279 | dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v); |
| 11068 | 5279 | upd_fld_set_virtual_col(ufield); | |
| 11069 | /* Set ufield->field_no to store the position of virtual column. */ | ||
| 11070 | 5279 | ufield->field_no = num_v; | |
| 11071 | |||
| 11072 |
4/6✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5278 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5279 times.
|
5279 | ut_ad(col->ord_part || online_ord_part); |
| 11073 |
2/2✓ Branch 0 taken 154 times.
✓ Branch 1 taken 5125 times.
|
5279 | if (old_old_v_val == nullptr) { |
| 11074 | 154 | ufield->old_v_val = static_cast<dfield_t *>( | |
| 11075 |
1/2✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
|
154 | mem_heap_alloc(uvect->heap, sizeof *ufield->old_v_val)); |
| 11076 | } else { | ||
| 11077 | UNIV_MEM_VALID(ufield, sizeof *ufield); | ||
| 11078 | 5125 | ufield->old_v_val->reset(); | |
| 11079 | } | ||
| 11080 | |||
| 11081 |
3/4✓ Branch 0 taken 5279 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5263 times.
✓ Branch 3 taken 16 times.
|
5279 | if (!field->is_null_in_record(old_row)) { |
| 11082 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 5232 times.
|
5263 | if (n_len == UNIV_SQL_NULL) { |
| 11083 |
2/4✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
|
31 | col->copy_type(dfield_get_type(&dfield)); |
| 11084 | } | ||
| 11085 | |||
| 11086 |
4/4✓ Branch 0 taken 104 times.
✓ Branch 1 taken 5159 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 85 times.
|
5263 | if (is_multi_value && !multi_value_calc_by_diff) { |
| 11087 | 19 | innobase_get_multi_value(prebuilt->m_mysql_table, i, &dfield, | |
| 11088 | nullptr, | ||
| 11089 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | static_cast<uint>(old_row - new_row), comp, |
| 11090 | uvect->per_stmt_heap); | ||
| 11091 | } else { | ||
| 11092 |
1/2✓ Branch 0 taken 5244 times.
✗ Branch 1 not taken.
|
5244 | buf = row_mysql_store_col_in_innobase_format( |
| 11093 | &dfield, (byte *)buf, true, old_mysql_row_col, col_pack_len, | ||
| 11094 | 5244 | comp, field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED, | |
| 11095 | 5244 | reinterpret_cast<const byte *>(field->zip_dict_data.str), | |
| 11096 | field->zip_dict_data.length, &prebuilt->compress_heap); | ||
| 11097 | } | ||
| 11098 | |||
| 11099 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 5178 times.
|
5263 | if (multi_value_calc_by_diff) { |
| 11100 | 85 | dfield_copy(ufield->old_v_val, &old_field); | |
| 11101 | 85 | dfield_copy(vfield, &old_field); | |
| 11102 | } else { | ||
| 11103 | 5178 | dfield_copy(ufield->old_v_val, &dfield); | |
| 11104 | 5178 | dfield_copy(vfield, &dfield); | |
| 11105 | } | ||
| 11106 | } else { | ||
| 11107 |
2/4✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | col->copy_type(dfield_get_type(ufield->old_v_val)); |
| 11108 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | dfield_set_null(ufield->old_v_val); |
| 11109 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | dfield_set_null(vfield); |
| 11110 | } | ||
| 11111 | 5279 | num_v++; | |
| 11112 | } else { | ||
| 11113 | /* Set ufield->field_no to store the position of column in | ||
| 11114 | clustered index. */ | ||
| 11115 | 18512973 | ufield->field_no = dict_col_get_clust_pos( | |
| 11116 |
1/2✓ Branch 0 taken 9256495 times.
✗ Branch 1 not taken.
|
9256478 | &prebuilt->table->cols[i - num_v], clust_index); |
| 11117 | #ifdef UNIV_DEBUG | ||
| 11118 |
2/2✓ Branch 0 taken 690 times.
✓ Branch 1 taken 9255810 times.
|
9256495 | if (clust_index->has_row_versions()) { |
| 11119 | 690 | dict_col_t *col = &prebuilt->table->cols[i - num_v]; | |
| 11120 | 690 | ufield->field_phy_pos = col->get_col_phy_pos(); | |
| 11121 | } | ||
| 11122 | #endif | ||
| 11123 | 9256500 | ufield->old_v_val = nullptr; | |
| 11124 | } | ||
| 11125 | 9261779 | n_changed++; | |
| 11126 | |||
| 11127 | /* If an FTS indexed column was changed by this | ||
| 11128 | UPDATE then we need to inform the FTS sub-system. | ||
| 11129 | |||
| 11130 | NOTE: Currently we re-index all FTS indexed columns | ||
| 11131 | even if only a subset of the FTS indexed columns | ||
| 11132 | have been updated. That is the reason we are | ||
| 11133 | checking only once here. Later we will need to | ||
| 11134 | note which columns have been updated and do | ||
| 11135 | selective processing. */ | ||
| 11136 |
3/4✓ Branch 0 taken 14998 times.
✓ Branch 1 taken 9246781 times.
✓ Branch 2 taken 14998 times.
✗ Branch 3 not taken.
|
9261779 | if (prebuilt->table->fts != nullptr && !is_virtual) { |
| 11137 | ulint offset; | ||
| 11138 | dict_table_t *innodb_table; | ||
| 11139 | |||
| 11140 | 14998 | innodb_table = prebuilt->table; | |
| 11141 | |||
| 11142 |
2/2✓ Branch 0 taken 14684 times.
✓ Branch 1 taken 314 times.
|
14998 | if (!changes_fts_column) { |
| 11143 |
1/2✓ Branch 0 taken 14684 times.
✗ Branch 1 not taken.
|
14684 | offset = row_upd_changes_fts_column(innodb_table, ufield); |
| 11144 | |||
| 11145 |
2/2✓ Branch 0 taken 14366 times.
✓ Branch 1 taken 318 times.
|
14684 | if (offset != ULINT_UNDEFINED) { |
| 11146 | 14366 | changes_fts_column = true; | |
| 11147 | } | ||
| 11148 | } | ||
| 11149 | |||
| 11150 |
2/2✓ Branch 0 taken 14393 times.
✓ Branch 1 taken 605 times.
|
14998 | if (!changes_fts_doc_col) { |
| 11151 |
1/2✓ Branch 0 taken 14393 times.
✗ Branch 1 not taken.
|
14393 | changes_fts_doc_col = row_upd_changes_doc_id(innodb_table, ufield); |
| 11152 | } | ||
| 11153 | } | ||
| 11154 |
2/2✓ Branch 0 taken 708 times.
✓ Branch 1 taken 138156149 times.
|
147418636 | } else if (is_virtual) { |
| 11155 |
1/2✓ Branch 0 taken 708 times.
✗ Branch 1 not taken.
|
708 | dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v); |
| 11156 |
2/4✓ Branch 0 taken 708 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 708 times.
✗ Branch 3 not taken.
|
708 | col->copy_type(dfield_get_type(vfield)); |
| 11157 | |||
| 11158 |
2/2✓ Branch 0 taken 89 times.
✓ Branch 1 taken 619 times.
|
708 | if (is_multi_value) { |
| 11159 | 89 | innobase_get_multi_value(prebuilt->m_mysql_table, i, vfield, nullptr, | |
| 11160 |
1/2✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
|
89 | static_cast<uint>(old_row - new_row), comp, |
| 11161 | uvect->per_stmt_heap); | ||
| 11162 | } else { | ||
| 11163 |
1/2✓ Branch 0 taken 619 times.
✗ Branch 1 not taken.
|
619 | buf = innodb_fill_old_vcol_val(prebuilt, vfield, o_len, |
| 11164 | old_mysql_row_col, col_pack_len, buf); | ||
| 11165 | } | ||
| 11166 | |||
| 11167 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 708 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 708 times.
|
708 | ut_ad(col->ord_part || online_ord_part); |
| 11168 | 708 | num_v++; | |
| 11169 | } | ||
| 11170 | } | ||
| 11171 | |||
| 11172 | /* If the update changes a column with an FTS index on it, we | ||
| 11173 | then add an update column node with a new document id to the | ||
| 11174 | other changes. We piggy back our changes on the normal UPDATE | ||
| 11175 | to reduce processing and IO overhead. */ | ||
| 11176 |
2/2✓ Branch 0 taken 14629464 times.
✓ Branch 1 taken 14407 times.
|
14643871 | if (!prebuilt->table->fts) { |
| 11177 | 14629464 | trx->fts_next_doc_id = 0; | |
| 11178 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 14394 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
14407 | } else if (changes_fts_column || changes_fts_doc_col) { |
| 11179 | 14394 | dict_table_t *innodb_table = prebuilt->table; | |
| 11180 | |||
| 11181 | 14394 | ufield = uvect->fields + n_changed; | |
| 11182 | |||
| 11183 |
2/2✓ Branch 0 taken 305 times.
✓ Branch 1 taken 14061 times.
|
14394 | if (!DICT_TF2_FLAG_IS_SET(innodb_table, DICT_TF2_FTS_HAS_DOC_ID)) { |
| 11184 | /* If Doc ID is managed by user, and if any | ||
| 11185 | FTS indexed column has been updated, its corresponding | ||
| 11186 | Doc ID must also be updated. Otherwise, return | ||
| 11187 | error */ | ||
| 11188 |
3/4✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 304 times.
|
305 | if (changes_fts_column && !changes_fts_doc_col) { |
| 11189 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | ib::warn(ER_IB_MSG_559) << "A new Doc ID must be supplied" |
| 11190 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | " while updating FTS indexed columns."; |
| 11191 | 1 | return (DB_FTS_INVALID_DOCID); | |
| 11192 | } | ||
| 11193 | |||
| 11194 | /* Doc ID must monotonically increase */ | ||
| 11195 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 304 times.
|
304 | ut_ad(innodb_table->fts->cache); |
| 11196 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 303 times.
|
304 | if (doc_id < prebuilt->table->fts->cache->next_doc_id) { |
| 11197 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ib::warn(ER_IB_MSG_560) << "FTS Doc ID must be larger than " |
| 11198 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | << innodb_table->fts->cache->next_doc_id - 1 |
| 11199 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | << " for table " << innodb_table->name; |
| 11200 | |||
| 11201 | 1 | return (DB_FTS_INVALID_DOCID); | |
| 11202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | } else if ((doc_id - prebuilt->table->fts->cache->next_doc_id) >= |
| 11203 | FTS_DOC_ID_MAX_STEP) { | ||
| 11204 | ✗ | ib::warn(ER_IB_MSG_561) | |
| 11205 | ✗ | << "Doc ID " << doc_id | |
| 11206 | << " is too" | ||
| 11207 | " big. Its difference with largest" | ||
| 11208 | ✗ | " Doc ID used " | |
| 11209 | ✗ | << prebuilt->table->fts->cache->next_doc_id - 1 | |
| 11210 | ✗ | << " cannot exceed or equal to " << FTS_DOC_ID_MAX_STEP; | |
| 11211 | } | ||
| 11212 | |||
| 11213 | 303 | trx->fts_next_doc_id = doc_id; | |
| 11214 | } else { | ||
| 11215 | /* If the Doc ID is a hidden column, it can't be | ||
| 11216 | changed by user */ | ||
| 11217 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14061 times.
|
14061 | ut_ad(!changes_fts_doc_col); |
| 11218 | |||
| 11219 | /* Doc ID column is hidden, a new Doc ID will be | ||
| 11220 | generated by following fts_update_doc_id() call */ | ||
| 11221 | 14061 | trx->fts_next_doc_id = 0; | |
| 11222 | } | ||
| 11223 | |||
| 11224 |
1/2✓ Branch 0 taken 14364 times.
✗ Branch 1 not taken.
|
14364 | fts_update_doc_id(innodb_table, ufield, &trx->fts_next_doc_id); |
| 11225 | |||
| 11226 | 14364 | ++n_changed; | |
| 11227 | 14364 | } else { | |
| 11228 | /* We have a Doc ID column, but none of FTS indexed | ||
| 11229 | columns are touched, nor the Doc ID column, so set | ||
| 11230 | fts_next_doc_id to UINT64_UNDEFINED, which means do not | ||
| 11231 | update the Doc ID column */ | ||
| 11232 | 13 | trx->fts_next_doc_id = UINT64_UNDEFINED; | |
| 11233 | } | ||
| 11234 | |||
| 11235 | 14643841 | uvect->n_fields = n_changed; | |
| 11236 | 14643841 | uvect->info_bits = 0; | |
| 11237 | |||
| 11238 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14643824 times.
|
14643841 | ut_a(buf <= (byte *)original_upd_buff + buff_len); |
| 11239 | |||
| 11240 |
3/4✓ Branch 0 taken 14643846 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 14643843 times.
|
14643824 | ut_ad(uvect->validate()); |
| 11241 | 14643843 | return (DB_SUCCESS); | |
| 11242 | } | ||
| 11243 | |||
| 11244 | /** | ||
| 11245 | Updates a row given as a parameter to a new value. Note that we are given | ||
| 11246 | whole rows, not just the fields which are updated: this incurs some | ||
| 11247 | overhead for CPU when we check which fields are actually updated. | ||
| 11248 | TODO: currently InnoDB does not prevent the 'Halloween problem': | ||
| 11249 | in a searched update a single row can get updated several times | ||
| 11250 | if its index columns are updated! | ||
| 11251 | @param[in] old_row Old row contents in MySQL format | ||
| 11252 | @param[out] new_row Updated row contents in MySQL format | ||
| 11253 | @return error number or 0 */ | ||
| 11254 | |||
| 11255 | 14643832 | int ha_innobase::update_row(const uchar *old_row, uchar *new_row) { | |
| 11256 | int err; | ||
| 11257 | |||
| 11258 | dberr_t error; | ||
| 11259 |
1/2✓ Branch 0 taken 14643850 times.
✗ Branch 1 not taken.
|
14643832 | trx_t *trx = thd_to_trx(m_user_thd); |
| 11260 | 14643850 | uint64_t new_counter = 0; | |
| 11261 | |||
| 11262 |
1/2✓ Branch 0 taken 14643857 times.
✗ Branch 1 not taken.
|
14643850 | DBUG_TRACE; |
| 11263 | |||
| 11264 | #ifdef WITH_WSREP | ||
| 11265 |
3/4✓ Branch 0 taken 14148087 times.
✓ Branch 1 taken 495770 times.
✓ Branch 2 taken 14148078 times.
✗ Branch 3 not taken.
|
14643857 | DEBUG_SYNC(m_user_thd, "ha_innobase_update_row"); |
| 11266 | #endif /* WITH_WSREP */ | ||
| 11267 | |||
| 11268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14643854 times.
|
14643848 | ut_a(m_prebuilt->trx == trx); |
| 11269 | |||
| 11270 |
7/8✓ Branch 0 taken 9 times.
✓ Branch 1 taken 14643845 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 14643849 times.
|
14643854 | if (high_level_read_only && !m_prebuilt->table->is_intrinsic()) { |
| 11271 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 11272 | 5 | return HA_ERR_TABLE_READONLY; | |
| 11273 |
2/4✓ Branch 0 taken 14643839 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14643839 times.
|
14643849 | } else if (!trx_is_started(trx)) { |
| 11274 | ✗ | ++trx->will_lock; | |
| 11275 | } | ||
| 11276 | |||
| 11277 |
2/2✓ Branch 0 taken 208129 times.
✓ Branch 1 taken 14435710 times.
|
14643839 | if (m_upd_buf == nullptr) { |
| 11278 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 208129 times.
|
208129 | ut_ad(m_upd_buf_size == 0); |
| 11279 | |||
| 11280 | /* Create a buffer for packing the fields of a record. Why | ||
| 11281 | table->reclength did not work here? Obviously, because char | ||
| 11282 | fields when packed actually became 1 byte longer, when we also | ||
| 11283 | stored the string length as the first byte. */ | ||
| 11284 | |||
| 11285 | 208129 | m_upd_buf_size = | |
| 11286 | 208129 | table->s->reclength + table->s->max_key_length + MAX_REF_PARTS * 3; | |
| 11287 | |||
| 11288 | 208129 | m_upd_buf = reinterpret_cast<uchar *>( | |
| 11289 |
1/2✓ Branch 0 taken 208129 times.
✗ Branch 1 not taken.
|
208129 | my_malloc(PSI_INSTRUMENT_ME, m_upd_buf_size, MYF(MY_WME))); |
| 11290 | |||
| 11291 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 208129 times.
|
208129 | if (m_upd_buf == nullptr) { |
| 11292 | ✗ | m_upd_buf_size = 0; | |
| 11293 | ✗ | return HA_ERR_OUT_OF_MEM; | |
| 11294 | } | ||
| 11295 | } | ||
| 11296 | |||
| 11297 |
1/2✓ Branch 0 taken 14643846 times.
✗ Branch 1 not taken.
|
14643839 | ha_statistic_increment(&System_status_var::ha_update_count); |
| 11298 | |||
| 11299 |
5/10✓ Branch 0 taken 14431969 times.
✓ Branch 1 taken 211877 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14431969 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14643846 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 14643846 times.
|
14643846 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 11300 | m_share->ib_table->is_corrupt)) | ||
| 11301 | ✗ | return HA_ERR_CRASHED; | |
| 11302 | |||
| 11303 | upd_t *uvect; | ||
| 11304 | |||
| 11305 |
2/2✓ Branch 0 taken 14453296 times.
✓ Branch 1 taken 190550 times.
|
14643846 | if (m_prebuilt->upd_node) { |
| 11306 | 14453296 | uvect = m_prebuilt->upd_node->update; | |
| 11307 | } else { | ||
| 11308 |
1/2✓ Branch 0 taken 190554 times.
✗ Branch 1 not taken.
|
190550 | uvect = row_get_prebuilt_update_vector(m_prebuilt); |
| 11309 | } | ||
| 11310 | |||
| 11311 | 14643850 | uvect->table = m_prebuilt->table; | |
| 11312 | 14643850 | uvect->mysql_table = table; | |
| 11313 | |||
| 11314 | /* Build an update vector from the modified fields in the rows | ||
| 11315 | (uses m_upd_buf of the handle) */ | ||
| 11316 | |||
| 11317 |
1/2✓ Branch 0 taken 14643842 times.
✗ Branch 1 not taken.
|
14643850 | error = calc_row_difference(uvect, old_row, new_row, table, m_upd_buf, |
| 11318 | m_upd_buf_size, m_prebuilt, m_user_thd); | ||
| 11319 | |||
| 11320 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14643840 times.
|
14643842 | if (error != DB_SUCCESS) { |
| 11321 | 2 | goto func_exit; | |
| 11322 | } | ||
| 11323 | |||
| 11324 |
8/10✓ Branch 0 taken 14643841 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13034586 times.
✓ Branch 3 taken 1609255 times.
✓ Branch 4 taken 13034585 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 13034584 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 14643839 times.
|
14643840 | if (!m_prebuilt->table->is_intrinsic() && TrxInInnoDB::is_aborted(trx)) { |
| 11325 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | innobase_rollback(ht, m_user_thd, false); |
| 11326 | |||
| 11327 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); |
| 11328 | } | ||
| 11329 | |||
| 11330 | /* This is not a delete */ | ||
| 11331 | 14643839 | m_prebuilt->upd_node->is_delete = false; | |
| 11332 | |||
| 11333 |
1/2✓ Branch 0 taken 14643832 times.
✗ Branch 1 not taken.
|
14643839 | error = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 11334 | |||
| 11335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14643832 times.
|
14643832 | if (error != DB_SUCCESS) { |
| 11336 | ✗ | goto func_exit; | |
| 11337 | } | ||
| 11338 | |||
| 11339 |
1/2✓ Branch 0 taken 14643834 times.
✗ Branch 1 not taken.
|
14643832 | error = row_update_for_mysql((byte *)old_row, m_prebuilt); |
| 11340 | |||
| 11341 |
2/2✓ Branch 0 taken 7315714 times.
✓ Branch 1 taken 7328121 times.
|
14643834 | if (dict_table_has_autoinc_col(m_prebuilt->table)) { |
| 11342 | 7315714 | new_counter = row_upd_get_new_autoinc_counter( | |
| 11343 |
1/2✓ Branch 0 taken 7315714 times.
✗ Branch 1 not taken.
|
7315714 | uvect, m_prebuilt->table->autoinc_field_no); |
| 11344 | } else { | ||
| 11345 | 7328121 | new_counter = 0; | |
| 11346 | } | ||
| 11347 | |||
| 11348 | /* We should handle the case if the AUTOINC counter has been | ||
| 11349 | updated, we want to update the counter accordingly. | ||
| 11350 | |||
| 11351 | We need to do some special AUTOINC handling for the following case: | ||
| 11352 | |||
| 11353 | INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ... | ||
| 11354 | |||
| 11355 | We need to use the AUTOINC counter that was actually used by | ||
| 11356 | MySQL in the UPDATE statement, which can be different from the | ||
| 11357 | value used in the INSERT statement. */ | ||
| 11358 | |||
| 11359 |
6/6✓ Branch 0 taken 14643272 times.
✓ Branch 1 taken 563 times.
✓ Branch 2 taken 14642658 times.
✓ Branch 3 taken 614 times.
✓ Branch 4 taken 675 times.
✓ Branch 5 taken 14643160 times.
|
29286493 | if (error == DB_SUCCESS && |
| 11360 | 14642658 | (new_counter != 0 || | |
| 11361 |
3/4✓ Branch 0 taken 79 times.
✓ Branch 1 taken 14642579 times.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
|
14642658 | (table->next_number_field && new_row == table->record[0] && |
| 11362 |
4/6✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
|
140 | thd_sql_command(m_user_thd) == SQLCOM_INSERT && |
| 11363 | 61 | m_prebuilt->allow_duplicates()))) { | |
| 11364 | ulonglong auto_inc; | ||
| 11365 | ulonglong col_max_value; | ||
| 11366 | |||
| 11367 |
2/2✓ Branch 0 taken 614 times.
✓ Branch 1 taken 61 times.
|
675 | if (new_counter != 0) { |
| 11368 | 614 | auto_inc = new_counter; | |
| 11369 | } else { | ||
| 11370 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | ut_ad(table->next_number_field != nullptr); |
| 11371 |
1/2✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
|
61 | auto_inc = table->next_number_field->val_int(); |
| 11372 | } | ||
| 11373 | |||
| 11374 | /* We need the upper limit of the col type to check for | ||
| 11375 | whether we update the table autoinc counter or not. */ | ||
| 11376 |
1/2✓ Branch 0 taken 675 times.
✗ Branch 1 not taken.
|
675 | col_max_value = table->found_next_number_field->get_max_int_value(); |
| 11377 | |||
| 11378 |
3/4✓ Branch 0 taken 675 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 672 times.
✓ Branch 3 taken 3 times.
|
675 | if (auto_inc <= col_max_value && auto_inc != 0) { |
| 11379 | ulonglong offset; | ||
| 11380 | ulonglong increment; | ||
| 11381 | |||
| 11382 | #ifdef WITH_WSREP | ||
| 11383 | /* Applier threads which are processing | ||
| 11384 | ROW events and don't go through server | ||
| 11385 | level autoinc processing, therefore | ||
| 11386 | m_prebuilt autoinc values don't get | ||
| 11387 | properly assigned. Fetch values from | ||
| 11388 | server side. */ | ||
| 11389 |
9/12✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 672 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 670 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 671 times.
|
672 | if (wsrep_on(current_thd) && wsrep_thd_is_applying(m_user_thd)) { |
| 11390 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | wsrep_thd_auto_increment_variables(current_thd, &offset, &increment); |
| 11391 | } else { | ||
| 11392 | 671 | offset = m_prebuilt->autoinc_offset; | |
| 11393 | 671 | increment = m_prebuilt->autoinc_increment; | |
| 11394 | } | ||
| 11395 | #else | ||
| 11396 | offset = m_prebuilt->autoinc_offset; | ||
| 11397 | increment = m_prebuilt->autoinc_increment; | ||
| 11398 | #endif /* WITH_WSREP */ | ||
| 11399 | |||
| 11400 | auto_inc = | ||
| 11401 |
1/2✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
|
672 | innobase_next_autoinc(auto_inc, 1, increment, offset, col_max_value); |
| 11402 | |||
| 11403 |
1/2✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
|
672 | error = innobase_set_max_autoinc(auto_inc); |
| 11404 | } | ||
| 11405 | } | ||
| 11406 | |||
| 11407 |
1/2✓ Branch 0 taken 14643832 times.
✗ Branch 1 not taken.
|
14643835 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 11408 | |||
| 11409 | 14643834 | func_exit: | |
| 11410 | |||
| 11411 | err = | ||
| 11412 |
1/2✓ Branch 0 taken 14643834 times.
✗ Branch 1 not taken.
|
14643834 | convert_error_code_to_mysql(error, m_prebuilt->table->flags, m_user_thd); |
| 11413 | |||
| 11414 | /* If success and no columns were updated. */ | ||
| 11415 |
4/4✓ Branch 0 taken 14643269 times.
✓ Branch 1 taken 565 times.
✓ Branch 2 taken 7291702 times.
✓ Branch 3 taken 7351567 times.
|
14643834 | if (err == 0 && uvect->n_fields == 0) { |
| 11416 | /* This is the same as success, but instructs | ||
| 11417 | MySQL that the row is not really updated and it | ||
| 11418 | should not increase the count of updated rows. | ||
| 11419 | This is fix for http://bugs.mysql.com/29157 */ | ||
| 11420 | 7291702 | err = HA_ERR_RECORD_IS_THE_SAME; | |
| 11421 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7352130 times.
|
7352132 | } else if (err == HA_FTS_INVALID_DOCID) { |
| 11422 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(HA_FTS_INVALID_DOCID, MYF(0)); |
| 11423 | } | ||
| 11424 | |||
| 11425 | /* Tell InnoDB server that there might be work for | ||
| 11426 | utility threads: */ | ||
| 11427 | |||
| 11428 |
1/2✓ Branch 0 taken 14643839 times.
✗ Branch 1 not taken.
|
14643834 | innobase_active_small(); |
| 11429 | |||
| 11430 | #ifdef WITH_WSREP | ||
| 11431 | /* Append key | ||
| 11432 | a. there is no error in update | ||
| 11433 | b. exec mode is local | ||
| 11434 | (it is workload executor node and not replicator node) | ||
| 11435 | c. wsrep is enabled | ||
| 11436 | d. No consistency check enforced. | ||
| 11437 | e. Ensure that bin-logging is enabled. | ||
| 11438 | Either mysql bin-logging or emulated bin logging. | ||
| 11439 | TODO: We allow replication even if binlog-format = STATEMENT. | ||
| 11440 | This is needed by pt-table-checksum. Now it is not a good idea | ||
| 11441 | to open this hook for pt-table-checksum but it exist like this for | ||
| 11442 | while now so to maintain compatibility we continue to provide it. | ||
| 11443 | With that there comes another existing dependency. */ | ||
| 11444 |
7/8✓ Branch 0 taken 7351572 times.
✓ Branch 1 taken 7292267 times.
✓ Branch 2 taken 7351572 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 620863 times.
✓ Branch 5 taken 6730709 times.
✓ Branch 6 taken 14022976 times.
✓ Branch 7 taken 620863 times.
|
14643839 | if (!err && wsrep_do_replication(m_user_thd)) { |
| 11445 |
3/8✓ Branch 0 taken 620863 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 620863 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 620863 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
620863 | DBUG_PRINT("wsrep", ("update row key")); |
| 11446 |
2/4✓ Branch 0 taken 620863 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 620863 times.
|
620863 | if (wsrep_append_keys(m_user_thd, |
| 11447 |
1/2✓ Branch 0 taken 620863 times.
✗ Branch 1 not taken.
|
620863 | wsrep_protocol_version >= 4 |
| 11448 | ? WSREP_SERVICE_KEY_UPDATE | ||
| 11449 | : WSREP_SERVICE_KEY_EXCLUSIVE, | ||
| 11450 | old_row, new_row)) { | ||
| 11451 | ✗ | DBUG_PRINT("wsrep", ("row key failed")); | |
| 11452 | ✗ | err = HA_ERR_INTERNAL_ERROR; | |
| 11453 | /* If we hit error during append key then we mark for complete | ||
| 11454 | transaction rollback */ | ||
| 11455 | ✗ | thd_mark_for_rollback(m_user_thd); | |
| 11456 | ✗ | goto wsrep_error; | |
| 11457 | } | ||
| 11458 | } | ||
| 11459 | 14022976 | wsrep_error: | |
| 11460 | #endif /* WITH_WSREP */ | ||
| 11461 | |||
| 11462 |
5/10✓ Branch 0 taken 14431954 times.
✓ Branch 1 taken 211885 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14431954 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14643839 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 14643839 times.
|
14643839 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 11463 | m_share->ib_table->is_corrupt)) | ||
| 11464 | ✗ | return HA_ERR_CRASHED; | |
| 11465 | |||
| 11466 | 14643839 | return err; | |
| 11467 | 14643845 | } | |
| 11468 | |||
| 11469 | /** Deletes a row given as the parameter. | ||
| 11470 | @return error number or 0 */ | ||
| 11471 | |||
| 11472 | 9162579 | int ha_innobase::delete_row( | |
| 11473 | const uchar *record) /*!< in: a row in MySQL format */ | ||
| 11474 | { | ||
| 11475 | dberr_t error; | ||
| 11476 |
1/2✓ Branch 0 taken 9162581 times.
✗ Branch 1 not taken.
|
9162579 | trx_t *trx = thd_to_trx(m_user_thd); |
| 11477 |
1/2✓ Branch 0 taken 9162580 times.
✗ Branch 1 not taken.
|
9162581 | TrxInInnoDB trx_in_innodb(trx); |
| 11478 | |||
| 11479 |
1/2✓ Branch 0 taken 9162581 times.
✗ Branch 1 not taken.
|
9162580 | DBUG_TRACE; |
| 11480 | |||
| 11481 |
5/10✓ Branch 0 taken 9162581 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9162581 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9162581 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9162581 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 9162581 times.
|
9162581 | if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) { |
| 11482 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 11483 | |||
| 11484 | ✗ | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 11485 | } | ||
| 11486 | |||
| 11487 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9162579 times.
|
9162581 | ut_a(m_prebuilt->trx == trx); |
| 11488 | |||
| 11489 |
6/8✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9162574 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 9162574 times.
|
9162579 | if (high_level_read_only && !m_prebuilt->table->is_intrinsic()) { |
| 11490 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 11491 | 5 | return HA_ERR_TABLE_READONLY; | |
| 11492 |
2/4✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9162575 times.
|
9162574 | } else if (!trx_is_started(trx)) { |
| 11493 | ✗ | ++trx->will_lock; | |
| 11494 | } | ||
| 11495 | |||
| 11496 |
1/2✓ Branch 0 taken 9162576 times.
✗ Branch 1 not taken.
|
9162575 | ha_statistic_increment(&System_status_var::ha_delete_count); |
| 11497 | |||
| 11498 |
5/10✓ Branch 0 taken 9079721 times.
✓ Branch 1 taken 82855 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9079721 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9162576 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 9162576 times.
|
9162576 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 11499 | m_share->ib_table->is_corrupt)) | ||
| 11500 | ✗ | return HA_ERR_CRASHED; | |
| 11501 | |||
| 11502 |
2/2✓ Branch 0 taken 126065 times.
✓ Branch 1 taken 9036511 times.
|
9162576 | if (!m_prebuilt->upd_node) { |
| 11503 |
1/2✓ Branch 0 taken 126066 times.
✗ Branch 1 not taken.
|
126065 | row_get_prebuilt_update_vector(m_prebuilt); |
| 11504 | } | ||
| 11505 | |||
| 11506 | /* This is a delete */ | ||
| 11507 | |||
| 11508 | 9162577 | m_prebuilt->upd_node->is_delete = true; | |
| 11509 | |||
| 11510 |
1/2✓ Branch 0 taken 9162576 times.
✗ Branch 1 not taken.
|
9162577 | error = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 11511 | |||
| 11512 |
1/2✓ Branch 0 taken 9162576 times.
✗ Branch 1 not taken.
|
9162576 | if (error == DB_SUCCESS) { |
| 11513 |
1/2✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
|
9162576 | error = row_update_for_mysql((byte *)record, m_prebuilt); |
| 11514 |
1/2✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
|
9162575 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 11515 | } | ||
| 11516 | |||
| 11517 | /* Tell the InnoDB server that there might be work for | ||
| 11518 | utility threads: */ | ||
| 11519 | |||
| 11520 |
1/2✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
|
9162575 | innobase_active_small(); |
| 11521 | |||
| 11522 | #ifdef WITH_WSREP | ||
| 11523 | /* Append key | ||
| 11524 | a. there is no error in delete | ||
| 11525 | b. exec mode is local | ||
| 11526 | (it is workload executor node and not replicator node) | ||
| 11527 | c. wsrep is enabled | ||
| 11528 | d. No consistency check enforced. | ||
| 11529 | e. Ensure that bin-logging is enabled. | ||
| 11530 | Either mysql bin-logging or emulated bin logging. | ||
| 11531 | TODO: We allow replication even if binlog-format = STATEMENT. | ||
| 11532 | This is needed by pt-table-checksum. Now it is not a god idea | ||
| 11533 | to open this hook for pt-table-checksum but it exist like this for | ||
| 11534 | while now so to maintain compatibility we continue to provide it. | ||
| 11535 | With that there comes another existing dependency. */ | ||
| 11536 |
7/8✓ Branch 0 taken 9162507 times.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 9162507 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22259 times.
✓ Branch 5 taken 9140248 times.
✓ Branch 6 taken 9140316 times.
✓ Branch 7 taken 22259 times.
|
9162575 | if (error == DB_SUCCESS && wsrep_do_replication(m_user_thd)) { |
| 11537 |
2/4✓ Branch 0 taken 22259 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 22259 times.
|
22259 | if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, record, |
| 11538 | NULL)) { | ||
| 11539 | ✗ | DBUG_PRINT("wsrep", ("delete fail")); | |
| 11540 | ✗ | error = DB_ERROR; | |
| 11541 | /* If we hit error during append key then we mark for complete | ||
| 11542 | transaction rollback */ | ||
| 11543 | ✗ | thd_mark_for_rollback(m_user_thd); | |
| 11544 | ✗ | goto wsrep_error; | |
| 11545 | } | ||
| 11546 | } | ||
| 11547 | |||
| 11548 | 9140316 | wsrep_error: | |
| 11549 | #endif /* WITH_WSREP */ | ||
| 11550 | |||
| 11551 |
5/10✓ Branch 0 taken 9079720 times.
✓ Branch 1 taken 82855 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9079720 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9162575 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 9162575 times.
|
9162575 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 11552 | m_share->ib_table->is_corrupt)) | ||
| 11553 | ✗ | return HA_ERR_CRASHED; | |
| 11554 | |||
| 11555 |
1/2✓ Branch 0 taken 9162575 times.
✗ Branch 1 not taken.
|
9162575 | return convert_error_code_to_mysql(error, m_prebuilt->table->flags, |
| 11556 | 9162575 | m_user_thd); | |
| 11557 | 9162580 | } | |
| 11558 | |||
| 11559 | /** Delete all rows from the table. | ||
| 11560 | @retval HA_ERR_WRONG_COMMAND if the table is transactional | ||
| 11561 | @retval 0 on success */ | ||
| 11562 | 63501 | int ha_innobase::delete_all_rows() { | |
| 11563 |
1/2✓ Branch 0 taken 63501 times.
✗ Branch 1 not taken.
|
63501 | DBUG_TRACE; |
| 11564 | |||
| 11565 |
3/4✓ Branch 0 taken 63501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2990 times.
✓ Branch 3 taken 60511 times.
|
63501 | if (!m_prebuilt->table->is_intrinsic()) { |
| 11566 | /* Transactional tables should use truncate(). */ | ||
| 11567 | 2990 | return HA_ERR_WRONG_COMMAND; | |
| 11568 | } | ||
| 11569 | |||
| 11570 |
1/2✓ Branch 0 taken 60511 times.
✗ Branch 1 not taken.
|
60511 | row_delete_all_rows(m_prebuilt->table); |
| 11571 | |||
| 11572 |
1/2✓ Branch 0 taken 60511 times.
✗ Branch 1 not taken.
|
60511 | dict_stats_update(m_prebuilt->table, DICT_STATS_EMPTY_TABLE); |
| 11573 | |||
| 11574 | 60511 | return 0; | |
| 11575 | 63501 | } | |
| 11576 | |||
| 11577 | /** Removes a new lock set on a row, if it was not read optimistically. This can | ||
| 11578 | be called after a row has been read in the processing of an UPDATE or a DELETE | ||
| 11579 | query, when the record doesn't match the WHERE condition. */ | ||
| 11580 | |||
| 11581 | 55779001 | void ha_innobase::unlock_row(void) { | |
| 11582 |
1/2✓ Branch 0 taken 55779001 times.
✗ Branch 1 not taken.
|
55779001 | DBUG_TRACE; |
| 11583 | |||
| 11584 | /* Consistent read does not take any locks, thus there is | ||
| 11585 | nothing to unlock. There is no locking for intrinsic table. */ | ||
| 11586 | |||
| 11587 |
4/4✓ Branch 0 taken 26860781 times.
✓ Branch 1 taken 28918220 times.
✓ Branch 2 taken 28918220 times.
✓ Branch 3 taken 26860781 times.
|
82639782 | if (m_prebuilt->select_lock_type == LOCK_NONE || |
| 11588 |
2/4✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26860781 times.
|
26860781 | m_prebuilt->table->is_intrinsic()) { |
| 11589 | 28918220 | return; | |
| 11590 | } | ||
| 11591 | |||
| 11592 |
1/2✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
|
26860781 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 11593 | |||
| 11594 |
2/4✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26860781 times.
|
26860781 | if (trx_in_innodb.is_aborted()) { |
| 11595 | ✗ | return; | |
| 11596 | } | ||
| 11597 | |||
| 11598 |
2/4✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26860781 times.
|
26860781 | ut_ad(!m_prebuilt->table->is_intrinsic()); |
| 11599 | |||
| 11600 | /* Ideally, this assert must be in the beginning of the function. | ||
| 11601 | But there are some calls to this function from the SQL layer when the | ||
| 11602 | transaction is in state TRX_STATE_NOT_STARTED. The check on | ||
| 11603 | m_prebuilt->select_lock_type above gets around this issue. */ | ||
| 11604 | |||
| 11605 |
3/10✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26860781 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 26860781 times.
|
26860781 | ut_ad(trx_state_eq(m_prebuilt->trx, TRX_STATE_ACTIVE) || |
| 11606 | trx_state_eq(m_prebuilt->trx, TRX_STATE_FORCED_ROLLBACK)); | ||
| 11607 | |||
| 11608 | /* The purpose of unlock_row() is to release locks held on non-matching row | ||
| 11609 | found during most recent row_search_mvcc() call. | ||
| 11610 | In higher isolation levels row_try_unlock() is a no-op, as we only set the | ||
| 11611 | m_prebuilt->new_rec_lock[i] when trx->releases_non_matching_rows(). | ||
| 11612 | In lower isolation levels row_try_unlock() will remove the record locks which | ||
| 11613 | were newly created during the most recent row_search_mvcc() (the record locks | ||
| 11614 | which were merely reused, are not released as they are still needed). | ||
| 11615 | @see handler::was_semi_consistent_read() for great explanation of what | ||
| 11616 | semi-consistent read mode is all about and why we don't call row_try_unlock() | ||
| 11617 | in case of ROW_READ_DID_SEMI_CONSISTENT, and reset the flag instead; in short | ||
| 11618 | a successful semi-consistent read means we didn't acquire any lock, so don't | ||
| 11619 | need to unlock anything if the row doesn't match the query. */ | ||
| 11620 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 26860742 times.
|
26860781 | if (m_prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT) { |
| 11621 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | ut_ad(m_prebuilt->new_rec_locks_count() == 0); |
| 11622 | 39 | m_prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT; | |
| 11623 | } | ||
| 11624 |
1/2✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
|
26860781 | m_prebuilt->try_unlock(false); |
| 11625 |
3/4✓ Branch 0 taken 26860781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26860781 times.
✓ Branch 3 taken 28918220 times.
|
55779001 | } |
| 11626 | |||
| 11627 | /* See handler.h and row0mysql.h for docs on this function. */ | ||
| 11628 | |||
| 11629 | 3594254 | bool ha_innobase::was_semi_consistent_read(void) { | |
| 11630 | 3594254 | return (m_prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT); | |
| 11631 | } | ||
| 11632 | |||
| 11633 | /* See handler.h and row0mysql.h for docs on this function. */ | ||
| 11634 | |||
| 11635 | 408780 | void ha_innobase::try_semi_consistent_read(bool yes) { | |
| 11636 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 408885 times.
|
408780 | ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 11637 | |||
| 11638 |
6/6✓ Branch 0 taken 196984 times.
✓ Branch 1 taken 211901 times.
✓ Branch 2 taken 242 times.
✓ Branch 3 taken 196737 times.
✓ Branch 4 taken 242 times.
✓ Branch 5 taken 408638 times.
|
408885 | if (yes && m_prebuilt->trx->allow_semi_consistent()) { |
| 11639 | 242 | m_prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT; | |
| 11640 | |||
| 11641 | } else { | ||
| 11642 | 408638 | m_prebuilt->row_read_type = ROW_READ_WITH_LOCKS; | |
| 11643 | } | ||
| 11644 | 408880 | } | |
| 11645 | |||
| 11646 | /** Initializes a handle to use an index. | ||
| 11647 | @return 0 or error number */ | ||
| 11648 | 102552345 | int ha_innobase::index_init(uint keynr, /*!< in: key (index) number */ | |
| 11649 | bool) /*!< in: 1 if result | ||
| 11650 | MUST be sorted | ||
| 11651 | according to index */ | ||
| 11652 | { | ||
| 11653 |
1/2✓ Branch 0 taken 102553218 times.
✗ Branch 1 not taken.
|
102552345 | DBUG_TRACE; |
| 11654 | |||
| 11655 |
1/2✓ Branch 0 taken 102553300 times.
✗ Branch 1 not taken.
|
205106534 | return change_active_index(keynr); |
| 11656 | 102553300 | } | |
| 11657 | |||
| 11658 | /** Currently does nothing. | ||
| 11659 | @return 0 */ | ||
| 11660 | |||
| 11661 | 105306167 | int ha_innobase::index_end(void) { | |
| 11662 |
1/2✓ Branch 0 taken 105306192 times.
✗ Branch 1 not taken.
|
105306167 | DBUG_TRACE; |
| 11663 | |||
| 11664 |
2/2✓ Branch 0 taken 55853 times.
✓ Branch 1 taken 105250339 times.
|
105306192 | if (m_prebuilt->index->last_sel_cur) { |
| 11665 |
1/2✓ Branch 0 taken 55853 times.
✗ Branch 1 not taken.
|
55853 | m_prebuilt->index->last_sel_cur->release(); |
| 11666 | } | ||
| 11667 | |||
| 11668 | 105306192 | active_index = MAX_KEY; | |
| 11669 | |||
| 11670 | 105306192 | in_range_check_pushed_down = false; | |
| 11671 | |||
| 11672 |
1/2✓ Branch 0 taken 105306187 times.
✗ Branch 1 not taken.
|
105306192 | m_ds_mrr.dsmrr_close(); |
| 11673 | |||
| 11674 | 105306195 | return 0; | |
| 11675 | 105306187 | } | |
| 11676 | |||
| 11677 | /** Converts a search mode flag understood by MySQL to a flag understood | ||
| 11678 | by InnoDB. */ | ||
| 11679 | 81101645 | page_cur_mode_t convert_search_mode_to_innobase(ha_rkey_function find_flag) { | |
| 11680 |
9/12✓ Branch 0 taken 75743761 times.
✓ Branch 1 taken 5323078 times.
✓ Branch 2 taken 27150 times.
✓ Branch 3 taken 6900 times.
✓ Branch 4 taken 240 times.
✓ Branch 5 taken 311 times.
✓ Branch 6 taken 84 times.
✓ Branch 7 taken 56 times.
✓ Branch 8 taken 115 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
81101645 | switch (find_flag) { |
| 11681 | 75743761 | case HA_READ_KEY_EXACT: | |
| 11682 | /* this does not require the index to be UNIQUE */ | ||
| 11683 | case HA_READ_KEY_OR_NEXT: | ||
| 11684 | 75743761 | return (PAGE_CUR_GE); | |
| 11685 | 5323078 | case HA_READ_AFTER_KEY: | |
| 11686 | 5323078 | return (PAGE_CUR_G); | |
| 11687 | 27150 | case HA_READ_BEFORE_KEY: | |
| 11688 | 27150 | return (PAGE_CUR_L); | |
| 11689 | 6900 | case HA_READ_KEY_OR_PREV: | |
| 11690 | case HA_READ_PREFIX_LAST: | ||
| 11691 | case HA_READ_PREFIX_LAST_OR_PREV: | ||
| 11692 | 6900 | return (PAGE_CUR_LE); | |
| 11693 | 240 | case HA_READ_MBR_CONTAIN: | |
| 11694 | 240 | return (PAGE_CUR_CONTAIN); | |
| 11695 | 311 | case HA_READ_MBR_INTERSECT: | |
| 11696 | 311 | return (PAGE_CUR_INTERSECT); | |
| 11697 | 84 | case HA_READ_MBR_WITHIN: | |
| 11698 | 84 | return (PAGE_CUR_WITHIN); | |
| 11699 | 56 | case HA_READ_MBR_DISJOINT: | |
| 11700 | 56 | return (PAGE_CUR_DISJOINT); | |
| 11701 | 115 | case HA_READ_MBR_EQUAL: | |
| 11702 | 115 | return (PAGE_CUR_MBR_EQUAL); | |
| 11703 | ✗ | case HA_READ_PREFIX: | |
| 11704 | ✗ | return (PAGE_CUR_UNSUPP); | |
| 11705 | ✗ | case HA_READ_INVALID: | |
| 11706 | ✗ | return (PAGE_CUR_UNSUPP); | |
| 11707 | /* do not use "default:" in order to produce a gcc warning: | ||
| 11708 | enumeration value '...' not handled in switch | ||
| 11709 | (if -Wswitch or -Wall is used) */ | ||
| 11710 | } | ||
| 11711 | |||
| 11712 | ✗ | my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality"); | |
| 11713 | |||
| 11714 | ✗ | return (PAGE_CUR_UNSUPP); | |
| 11715 | } | ||
| 11716 | |||
| 11717 | #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND) | ||
| 11718 | 413377 | static bool template_new_is_valid(mysql_row_templ_t *t_new, | |
| 11719 | const mysql_row_templ_t *t_saved, | ||
| 11720 | int n_template) { | ||
| 11721 | /* Percona might modify the template field `rec_field_no`, after its creation, | ||
| 11722 | in row0sel.cc:use_secondary_index. | ||
| 11723 | In order to compare the new template and the previous one, we overwrite | ||
| 11724 | `rec_field_no`. | ||
| 11725 | The new template is discarded and used just for debug purposes so we do not | ||
| 11726 | need to restore the previous value. */ | ||
| 11727 |
2/2✓ Branch 0 taken 1032331 times.
✓ Branch 1 taken 413377 times.
|
1445708 | for (auto i = 0; i < n_template; ++i) { |
| 11728 | 1032331 | auto *templ_new = t_new + i; | |
| 11729 | 1032331 | const auto *templ_saved = t_saved + i; | |
| 11730 | 1032331 | templ_new->rec_field_no = templ_saved->rec_field_no; | |
| 11731 | } | ||
| 11732 | |||
| 11733 | 413377 | return !memcmp(t_new, t_saved, n_template * sizeof(mysql_row_templ_t)); | |
| 11734 | } | ||
| 11735 | #endif | ||
| 11736 | |||
| 11737 | /* | ||
| 11738 | BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED | ||
| 11739 | --------------------------------------------------- | ||
| 11740 | The following does not cover all the details, but explains how we determine | ||
| 11741 | the start of a new SQL statement, and what is associated with it. | ||
| 11742 | |||
| 11743 | For each table in the database the MySQL interpreter may have several | ||
| 11744 | table handle instances in use, also in a single SQL query. For each table | ||
| 11745 | handle instance there is an InnoDB 'm_prebuilt' struct which contains most | ||
| 11746 | of the InnoDB data associated with this table handle instance. | ||
| 11747 | |||
| 11748 | A) if the user has not explicitly set any MySQL table level locks: | ||
| 11749 | |||
| 11750 | 1) MySQL calls ::external_lock to set an 'intention' table level lock on | ||
| 11751 | the table of the handle instance. There we set | ||
| 11752 | m_prebuilt->sql_stat_start = true. The flag sql_stat_start should be set | ||
| 11753 | true if we are taking this table handle instance to use in a new SQL | ||
| 11754 | statement issued by the user. We also increment trx->n_mysql_tables_in_use. | ||
| 11755 | |||
| 11756 | 2) If m_prebuilt->sql_stat_start == true we 'pre-compile' the MySQL search | ||
| 11757 | instructions to m_prebuilt->template of the table handle instance in | ||
| 11758 | ::index_read. The template is used to save CPU time in large joins. | ||
| 11759 | |||
| 11760 | 3) In row_search_for_mysql, if m_prebuilt->sql_stat_start is true, we | ||
| 11761 | allocate a new consistent read view for the trx if it does not yet have one, | ||
| 11762 | or in the case of a locking read, set an InnoDB 'intention' table level | ||
| 11763 | lock on the table. | ||
| 11764 | |||
| 11765 | 4) We do the SELECT. MySQL may repeatedly call ::index_read for the | ||
| 11766 | same table handle instance, if it is a join. | ||
| 11767 | |||
| 11768 | 5) When the SELECT ends, MySQL removes its intention table level locks | ||
| 11769 | in ::external_lock. When trx->n_mysql_tables_in_use drops to zero, | ||
| 11770 | (a) we execute a COMMIT there if the autocommit is on, | ||
| 11771 | (b) we also release possible 'SQL statement level resources' InnoDB may | ||
| 11772 | have for this SQL statement. The MySQL interpreter does NOT execute | ||
| 11773 | autocommit for pure read transactions, though it should. That is why the | ||
| 11774 | table handler in that case has to execute the COMMIT in ::external_lock. | ||
| 11775 | |||
| 11776 | B) If the user has explicitly set MySQL table level locks, then MySQL | ||
| 11777 | does NOT call ::external_lock at the start of the statement. To determine | ||
| 11778 | when we are at the start of a new SQL statement we at the start of | ||
| 11779 | ::index_read also compare the query id to the latest query id where the | ||
| 11780 | table handle instance was used. If it has changed, we know we are at the | ||
| 11781 | start of a new SQL statement. Since the query id can theoretically | ||
| 11782 | overwrap, we use this test only as a secondary way of determining the | ||
| 11783 | start of a new SQL statement. */ | ||
| 11784 | |||
| 11785 | /** Positions an index cursor to the index specified in the handle. Fetches the | ||
| 11786 | row if any. | ||
| 11787 | @return 0, HA_ERR_KEY_NOT_FOUND, or error number */ | ||
| 11788 | |||
| 11789 | 80058933 | int ha_innobase::index_read( | |
| 11790 | uchar *buf, /*!< in/out: buffer for the returned | ||
| 11791 | row */ | ||
| 11792 | const uchar *key_ptr, /*!< in: key value; if this is NULL | ||
| 11793 | we position the cursor at the | ||
| 11794 | start or end of index; this can | ||
| 11795 | also contain an InnoDB row id, in | ||
| 11796 | which case key_len is the InnoDB | ||
| 11797 | row id length; the key value can | ||
| 11798 | also be a prefix of a full key value, | ||
| 11799 | and the last column can be a prefix | ||
| 11800 | of a full column */ | ||
| 11801 | uint key_len, /*!< in: key value length */ | ||
| 11802 | enum ha_rkey_function find_flag) /*!< in: search flags from my_base.h */ | ||
| 11803 | { | ||
| 11804 |
1/2✓ Branch 0 taken 80059438 times.
✗ Branch 1 not taken.
|
80058933 | DBUG_TRACE; |
| 11805 |
3/4✓ Branch 0 taken 77293215 times.
✓ Branch 1 taken 2766223 times.
✓ Branch 2 taken 77293213 times.
✗ Branch 3 not taken.
|
80059438 | DEBUG_SYNC_C("ha_innobase_index_read_begin"); |
| 11806 | |||
| 11807 |
3/4✓ Branch 0 taken 80059410 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 80059414 times.
|
80059436 | ut_a(m_prebuilt->trx == thd_to_trx(m_user_thd)); |
| 11808 |
4/6✓ Branch 0 taken 4845730 times.
✓ Branch 1 taken 75213684 times.
✓ Branch 2 taken 4845730 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 80059364 times.
|
80059414 | ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT); |
| 11809 | |||
| 11810 |
1/2✓ Branch 0 taken 80059375 times.
✗ Branch 1 not taken.
|
80059364 | ha_statistic_increment(&System_status_var::ha_read_key_count); |
| 11811 | |||
| 11812 |
8/14✓ Branch 0 taken 80059391 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79417039 times.
✓ Branch 3 taken 642352 times.
✓ Branch 4 taken 79417027 times.
✓ Branch 5 taken 642348 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 79417027 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 80059375 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 80059375 times.
|
80059375 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 11813 | m_share->ib_table && m_share->ib_table->is_corrupt)) { | ||
| 11814 | ✗ | return HA_ERR_CRASHED; | |
| 11815 | } | ||
| 11816 | |||
| 11817 | 80059375 | dict_index_t *index = m_prebuilt->index; | |
| 11818 | |||
| 11819 |
6/8✓ Branch 0 taken 80059372 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 80059334 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 80059309 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 80059337 times.
|
80059375 | if (index == nullptr || index->is_corrupted()) { |
| 11820 | ✗ | m_prebuilt->index_usable = false; | |
| 11821 | ✗ | return HA_ERR_CRASHED; | |
| 11822 | } | ||
| 11823 | |||
| 11824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 80059337 times.
|
80059337 | if (!m_prebuilt->index_usable) { |
| 11825 | ✗ | return index->is_corrupted() ? HA_ERR_INDEX_CORRUPT | |
| 11826 | ✗ | : HA_ERR_TABLE_DEF_CHANGED; | |
| 11827 | } | ||
| 11828 | |||
| 11829 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 80059337 times.
|
80059337 | if (index->type & DICT_FTS) { |
| 11830 | ✗ | return HA_ERR_KEY_NOT_FOUND; | |
| 11831 | } | ||
| 11832 | |||
| 11833 | /* For R-Tree index, we will always place the page lock to | ||
| 11834 | pages being searched */ | ||
| 11835 |
3/4✓ Branch 0 taken 80059309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 80059068 times.
|
80059337 | if (dict_index_is_spatial(index)) { |
| 11836 | 241 | ++m_prebuilt->trx->will_lock; | |
| 11837 | } | ||
| 11838 | |||
| 11839 | /* Note that if the index for which the search template is built is not | ||
| 11840 | necessarily m_prebuilt->index, but can also be the clustered index */ | ||
| 11841 | |||
| 11842 |
7/8✓ Branch 0 taken 54301703 times.
✓ Branch 1 taken 25757606 times.
✓ Branch 2 taken 54301447 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 53888268 times.
✓ Branch 5 taken 413179 times.
✓ Branch 6 taken 53888333 times.
✓ Branch 7 taken 26170720 times.
|
80059309 | if (m_prebuilt->sql_stat_start && !can_reuse_mysql_template()) { |
| 11843 |
1/2✓ Branch 0 taken 53888621 times.
✗ Branch 1 not taken.
|
53888333 | build_template(false); |
| 11844 | } | ||
| 11845 | |||
| 11846 | #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND) | ||
| 11847 | /* valgrind complains about some of uninitialized bytes. skip it for now. */ | ||
| 11848 |
7/8✓ Branch 0 taken 54301826 times.
✓ Branch 1 taken 25757515 times.
✓ Branch 2 taken 54301854 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 413377 times.
✓ Branch 5 taken 53888477 times.
✓ Branch 6 taken 413377 times.
✓ Branch 7 taken 79645992 times.
|
80059341 | if (m_prebuilt->sql_stat_start && can_reuse_mysql_template()) { |
| 11849 | /* confirm mysql_template contents are same */ | ||
| 11850 | 413377 | const auto n_template_save = m_prebuilt->n_template; | |
| 11851 | 413377 | mysql_row_templ_t *mysql_template_save = m_prebuilt->mysql_template; | |
| 11852 | 413377 | m_prebuilt->mysql_template = nullptr; | |
| 11853 |
1/2✓ Branch 0 taken 413377 times.
✗ Branch 1 not taken.
|
413377 | build_template(false); |
| 11854 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 413377 times.
|
413377 | ut_a(m_prebuilt->n_template == n_template_save); |
| 11855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 413377 times.
|
413377 | ut_a(template_new_is_valid(m_prebuilt->mysql_template, mysql_template_save, |
| 11856 | n_template_save)); | ||
| 11857 | 413377 | ut::free(m_prebuilt->mysql_template); | |
| 11858 | 413377 | m_prebuilt->mysql_template = mysql_template_save; | |
| 11859 | } | ||
| 11860 | #endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */ | ||
| 11861 | |||
| 11862 |
2/2✓ Branch 0 taken 75213523 times.
✓ Branch 1 taken 4845846 times.
|
80059369 | if (key_ptr != nullptr) { |
| 11863 | /* Convert the search key value to InnoDB format into | ||
| 11864 | m_prebuilt->search_tuple */ | ||
| 11865 | |||
| 11866 | 75213523 | row_sel_convert_mysql_key_to_innobase( | |
| 11867 | 75213523 | m_prebuilt->search_tuple, m_prebuilt->srch_key_val1, | |
| 11868 |
1/2✓ Branch 0 taken 75213567 times.
✗ Branch 1 not taken.
|
75213523 | m_prebuilt->srch_key_val_len, index, key_ptr, key_len); |
| 11869 | |||
| 11870 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75213567 times.
|
75213567 | assert(m_prebuilt->search_tuple->n_fields > 0); |
| 11871 | } else { | ||
| 11872 | /* We position the cursor to the last or the first entry | ||
| 11873 | in the index */ | ||
| 11874 | |||
| 11875 |
1/2✓ Branch 0 taken 4845708 times.
✗ Branch 1 not taken.
|
4845846 | dtuple_set_n_fields(m_prebuilt->search_tuple, 0); |
| 11876 | } | ||
| 11877 | |||
| 11878 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 80059116 times.
|
80059275 | ut_ad(m_prebuilt->m_mysql_handler == this); |
| 11879 | 80059116 | m_prebuilt->m_stop_tuple_found = false; | |
| 11880 |
6/6✓ Branch 0 taken 405682 times.
✓ Branch 1 taken 79653434 times.
✓ Branch 2 taken 359595 times.
✓ Branch 3 taken 46087 times.
✓ Branch 4 taken 359595 times.
✓ Branch 5 taken 79699521 times.
|
80059116 | if (end_range != nullptr && m_prebuilt->is_reading_range()) { |
| 11881 | 359595 | row_sel_convert_mysql_key_to_innobase( | |
| 11882 | 359595 | m_prebuilt->m_stop_tuple, m_prebuilt->srch_key_val2, | |
| 11883 |
1/2✓ Branch 0 taken 359625 times.
✗ Branch 1 not taken.
|
359595 | m_prebuilt->srch_key_val_len, index, end_range->key, end_range->length); |
| 11884 | } else { | ||
| 11885 |
1/2✓ Branch 0 taken 79699514 times.
✗ Branch 1 not taken.
|
79699521 | dtuple_set_n_fields(m_prebuilt->m_stop_tuple, 0); |
| 11886 | } | ||
| 11887 | |||
| 11888 |
1/2✓ Branch 0 taken 80058832 times.
✗ Branch 1 not taken.
|
80059139 | page_cur_mode_t mode = convert_search_mode_to_innobase(find_flag); |
| 11889 | |||
| 11890 | 80058832 | ulint match_mode = 0; | |
| 11891 | |||
| 11892 |
2/2✓ Branch 0 taken 75072388 times.
✓ Branch 1 taken 4986444 times.
|
80058832 | if (find_flag == HA_READ_KEY_EXACT) { |
| 11893 | 75072388 | match_mode = ROW_SEL_EXACT; | |
| 11894 | |||
| 11895 |
2/2✓ Branch 0 taken 2331 times.
✓ Branch 1 taken 4984113 times.
|
4986444 | } else if (find_flag == HA_READ_PREFIX_LAST) { |
| 11896 | 2331 | match_mode = ROW_SEL_EXACT_PREFIX; | |
| 11897 | } | ||
| 11898 | |||
| 11899 | 80058832 | m_last_match_mode = (uint)match_mode; | |
| 11900 | |||
| 11901 | dberr_t ret; | ||
| 11902 | |||
| 11903 |
1/2✓ Branch 0 taken 80059086 times.
✗ Branch 1 not taken.
|
80058832 | if (mode != PAGE_CUR_UNSUPP) { |
| 11904 |
1/2✓ Branch 0 taken 80058918 times.
✗ Branch 1 not taken.
|
80059086 | ret = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 11905 | |||
| 11906 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 80058918 times.
|
80058918 | if (ret != DB_SUCCESS) { |
| 11907 | ✗ | return convert_error_code_to_mysql(ret, m_prebuilt->table->flags, | |
| 11908 | ✗ | m_user_thd); | |
| 11909 | } | ||
| 11910 | |||
| 11911 |
3/4✓ Branch 0 taken 80059158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71224282 times.
✓ Branch 3 taken 8834876 times.
|
80058918 | if (!m_prebuilt->table->is_intrinsic()) { |
| 11912 |
3/4✓ Branch 0 taken 71224283 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 71224282 times.
|
71224282 | if (TrxInInnoDB::is_aborted(m_prebuilt->trx)) { |
| 11913 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | innobase_rollback(ht, m_user_thd, false); |
| 11914 | |||
| 11915 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); |
| 11916 | } | ||
| 11917 | |||
| 11918 |
1/2✓ Branch 0 taken 71224035 times.
✗ Branch 1 not taken.
|
71224282 | m_prebuilt->ins_sel_stmt = thd_is_ins_sel_stmt(m_user_thd); |
| 11919 | |||
| 11920 |
1/2✓ Branch 0 taken 71224499 times.
✗ Branch 1 not taken.
|
71224035 | ret = row_search_mvcc(buf, mode, m_prebuilt, match_mode, 0); |
| 11921 | |||
| 11922 | } else { | ||
| 11923 |
1/2✓ Branch 0 taken 8834923 times.
✗ Branch 1 not taken.
|
8834876 | m_prebuilt->session = thd_to_innodb_session(m_user_thd); |
| 11924 | |||
| 11925 |
1/2✓ Branch 0 taken 8834923 times.
✗ Branch 1 not taken.
|
8834923 | ret = row_search_no_mvcc(buf, mode, m_prebuilt, match_mode, 0); |
| 11926 | } | ||
| 11927 | |||
| 11928 |
1/2✓ Branch 0 taken 80059758 times.
✗ Branch 1 not taken.
|
80059422 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 11929 | } else { | ||
| 11930 | ✗ | ret = DB_UNSUPPORTED; | |
| 11931 | } | ||
| 11932 | |||
| 11933 |
9/14✓ Branch 0 taken 80059488 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 79417145 times.
✓ Branch 3 taken 642343 times.
✓ Branch 4 taken 79417128 times.
✓ Branch 5 taken 642376 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 79417128 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 80059504 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 80059504 times.
|
80059504 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 11934 | m_share->ib_table && m_share->ib_table->is_corrupt)) { | ||
| 11935 | ✗ | return HA_ERR_CRASHED; | |
| 11936 | } | ||
| 11937 | |||
| 11938 |
2/4✓ Branch 0 taken 80059503 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 80059503 times.
|
80059504 | DBUG_EXECUTE_IF("ib_select_query_failure", ret = DB_ERROR;); |
| 11939 | |||
| 11940 | int error; | ||
| 11941 | |||
| 11942 |
5/6✓ Branch 0 taken 59431709 times.
✓ Branch 1 taken 19799868 times.
✓ Branch 2 taken 827412 times.
✓ Branch 3 taken 167 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 347 times.
|
80059503 | switch (ret) { |
| 11943 | 59431709 | case DB_SUCCESS: | |
| 11944 | 59431709 | error = 0; | |
| 11945 |
2/2✓ Branch 0 taken 44538112 times.
✓ Branch 1 taken 14893597 times.
|
59431709 | if (m_prebuilt->table->is_system_table) { |
| 11946 |
1/2✓ Branch 0 taken 44538118 times.
✗ Branch 1 not taken.
|
44538105 | srv_stats.n_system_rows_read.add( |
| 11947 |
1/2✓ Branch 0 taken 44538105 times.
✗ Branch 1 not taken.
|
44538112 | thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1); |
| 11948 | } else { | ||
| 11949 |
2/4✓ Branch 0 taken 14893598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14893600 times.
✗ Branch 3 not taken.
|
14893597 | srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd), |
| 11950 | 1); | ||
| 11951 | } | ||
| 11952 | 59431718 | break; | |
| 11953 | |||
| 11954 | 19799868 | case DB_RECORD_NOT_FOUND: | |
| 11955 | 19799868 | error = HA_ERR_KEY_NOT_FOUND; | |
| 11956 | 19799868 | break; | |
| 11957 | |||
| 11958 | 827412 | case DB_END_OF_INDEX: | |
| 11959 | 827412 | error = HA_ERR_KEY_NOT_FOUND; | |
| 11960 | 827412 | break; | |
| 11961 | |||
| 11962 | 167 | case DB_TABLESPACE_DELETED: | |
| 11963 | 167 | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 11964 |
1/2✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
|
167 | ER_TABLESPACE_DISCARDED, table->s->table_name.str); |
| 11965 | |||
| 11966 | 167 | error = HA_ERR_NO_SUCH_TABLE; | |
| 11967 | 167 | break; | |
| 11968 | |||
| 11969 | ✗ | case DB_TABLESPACE_NOT_FOUND: | |
| 11970 | |||
| 11971 | ✗ | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 11972 | ✗ | ER_TABLESPACE_MISSING, table->s->table_name.str); | |
| 11973 | |||
| 11974 | ✗ | error = HA_ERR_TABLESPACE_MISSING; | |
| 11975 | ✗ | break; | |
| 11976 | |||
| 11977 | 347 | default: | |
| 11978 |
1/2✓ Branch 0 taken 334 times.
✗ Branch 1 not taken.
|
347 | error = convert_error_code_to_mysql(ret, m_prebuilt->table->flags, |
| 11979 | m_user_thd); | ||
| 11980 | |||
| 11981 | 334 | break; | |
| 11982 | } | ||
| 11983 | |||
| 11984 | 80059499 | return error; | |
| 11985 | 80059500 | } | |
| 11986 | |||
| 11987 | /** The following functions works like index_read, but it find the last | ||
| 11988 | row with the current key value or prefix. | ||
| 11989 | @return 0, HA_ERR_KEY_NOT_FOUND, or an error code */ | ||
| 11990 | |||
| 11991 | 492 | int ha_innobase::index_read_last( | |
| 11992 | uchar *buf, /*!< out: fetched row */ | ||
| 11993 | const uchar *key_ptr, /*!< in: key value, or a prefix of a full | ||
| 11994 | key value */ | ||
| 11995 | uint key_len) /*!< in: length of the key val or prefix | ||
| 11996 | in bytes */ | ||
| 11997 | { | ||
| 11998 | 492 | return (index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST)); | |
| 11999 | } | ||
| 12000 | |||
| 12001 | /** Get the index for a handle. Does not change active index. | ||
| 12002 | @return NULL or index instance. */ | ||
| 12003 | |||
| 12004 | 132774020 | dict_index_t *ha_innobase::innobase_get_index( | |
| 12005 | uint keynr) /*!< in: use this index; MAX_KEY means always | ||
| 12006 | clustered index, even if it was internally | ||
| 12007 | generated by InnoDB */ | ||
| 12008 | { | ||
| 12009 | KEY *key; | ||
| 12010 | dict_index_t *index; | ||
| 12011 | |||
| 12012 |
1/2✓ Branch 0 taken 132775182 times.
✗ Branch 1 not taken.
|
132774020 | DBUG_TRACE; |
| 12013 | |||
| 12014 |
3/4✓ Branch 0 taken 132327887 times.
✓ Branch 1 taken 447295 times.
✓ Branch 2 taken 132327993 times.
✗ Branch 3 not taken.
|
132775182 | if (keynr != MAX_KEY && table->s->keys > 0) { |
| 12015 | 132327993 | key = table->key_info + keynr; | |
| 12016 | |||
| 12017 | 132327993 | index = innobase_index_lookup(m_share, keynr); | |
| 12018 | |||
| 12019 |
1/2✓ Branch 0 taken 132327669 times.
✗ Branch 1 not taken.
|
132327397 | if (index != nullptr) { |
| 12020 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132326580 times.
|
132327669 | ut_a(ut_strcmp(index->name, key->name) == 0); |
| 12021 | } else { | ||
| 12022 | /* Can't find index with keynr in the translation | ||
| 12023 | table. Only print message if the index translation | ||
| 12024 | table exists */ | ||
| 12025 | ✗ | if (m_share->idx_trans_tbl.index_mapping != nullptr) { | |
| 12026 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX_WITH_KEY_NO, | |
| 12027 | key ? key->name : "NULL", keynr, | ||
| 12028 | m_prebuilt->table->name.m_name); | ||
| 12029 | } | ||
| 12030 | |||
| 12031 | ✗ | index = dict_table_get_index_on_name(m_prebuilt->table, key->name); | |
| 12032 | } | ||
| 12033 | } else { | ||
| 12034 | 447189 | key = nullptr; | |
| 12035 |
1/2✓ Branch 0 taken 447213 times.
✗ Branch 1 not taken.
|
447189 | index = m_prebuilt->table->first_index(); |
| 12036 | } | ||
| 12037 | |||
| 12038 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132773793 times.
|
132773793 | if (index == nullptr) { |
| 12039 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX_FROM_DICT_CACHE, keynr, | |
| 12040 | key ? key->name : "NULL", m_prebuilt->table->name.m_name); | ||
| 12041 | } | ||
| 12042 | |||
| 12043 | 132775167 | return index; | |
| 12044 | 132773793 | } | |
| 12045 | |||
| 12046 | /** Changes the active index of a handle. | ||
| 12047 | @return 0 or error code */ | ||
| 12048 | 106895280 | int ha_innobase::change_active_index( | |
| 12049 | uint keynr) /*!< in: use this index; MAX_KEY means always clustered | ||
| 12050 | index, even if it was internally generated by | ||
| 12051 | InnoDB */ | ||
| 12052 | { | ||
| 12053 |
1/2✓ Branch 0 taken 106895879 times.
✗ Branch 1 not taken.
|
106895280 | DBUG_TRACE; |
| 12054 | |||
| 12055 |
9/14✓ Branch 0 taken 106895780 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 106895763 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 106895763 times.
✓ Branch 5 taken 116 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 106895763 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 106895879 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 106895879 times.
|
106895879 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 12056 | m_share->ib_table && m_share->ib_table->is_corrupt)) | ||
| 12057 | ✗ | return HA_ERR_CRASHED; | |
| 12058 | |||
| 12059 |
2/4✓ Branch 0 taken 106895829 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 106895821 times.
|
106895879 | ut_ad(m_user_thd == ha_thd()); |
| 12060 |
2/4✓ Branch 0 taken 106895508 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 106895666 times.
|
106895821 | ut_a(m_prebuilt->trx == thd_to_trx(m_user_thd)); |
| 12061 | |||
| 12062 |
1/2✓ Branch 0 taken 106895636 times.
✗ Branch 1 not taken.
|
106895666 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 12063 | |||
| 12064 |
8/10✓ Branch 0 taken 106895560 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 106837580 times.
✓ Branch 3 taken 57980 times.
✓ Branch 4 taken 106837601 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 106837599 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 106895579 times.
|
106895636 | if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) { |
| 12065 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | innobase_rollback(ht, m_user_thd, false); |
| 12066 | |||
| 12067 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); |
| 12068 | } | ||
| 12069 | |||
| 12070 | 106895579 | active_index = keynr; | |
| 12071 | |||
| 12072 |
1/2✓ Branch 0 taken 106895888 times.
✗ Branch 1 not taken.
|
106895579 | m_prebuilt->index = innobase_get_index(keynr); |
| 12073 | |||
| 12074 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 106895888 times.
|
106895888 | if (m_prebuilt->index == nullptr) { |
| 12075 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_ACTIVE_INDEX_CHANGE_FAILED, keynr); | |
| 12076 | ✗ | m_prebuilt->index_usable = false; | |
| 12077 | ✗ | return 1; | |
| 12078 | } | ||
| 12079 | |||
| 12080 |
1/2✓ Branch 0 taken 106895590 times.
✗ Branch 1 not taken.
|
106895888 | m_prebuilt->index_usable = m_prebuilt->index->is_usable(m_prebuilt->trx); |
| 12081 | |||
| 12082 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 106895569 times.
|
106895590 | if (!m_prebuilt->index_usable) { |
| 12083 |
3/4✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 9 times.
|
21 | if (m_prebuilt->index->is_corrupted()) { |
| 12084 | char table_name[MAX_FULL_NAME_LEN + 1]; | ||
| 12085 | |||
| 12086 | 12 | innobase_format_name(table_name, sizeof table_name, | |
| 12087 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | m_prebuilt->index->table->name.m_name); |
| 12088 | |||
| 12089 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
|
12 | if (m_prebuilt->index->is_clustered()) { |
| 12090 | ✗ | ut_ad(m_prebuilt->table->is_corrupted()); | |
| 12091 | ✗ | push_warning_printf(m_user_thd, Sql_condition::SL_WARNING, | |
| 12092 | HA_ERR_TABLE_CORRUPT, | ||
| 12093 | "InnoDB: Table %s is corrupted.", table_name); | ||
| 12094 | ✗ | return HA_ERR_TABLE_CORRUPT; | |
| 12095 | } else { | ||
| 12096 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | push_warning_printf(m_user_thd, Sql_condition::SL_WARNING, |
| 12097 | HA_ERR_INDEX_CORRUPT, | ||
| 12098 | "InnoDB: Index %s for table %s is" | ||
| 12099 | " marked as corrupted", | ||
| 12100 | 12 | m_prebuilt->index->name(), table_name); | |
| 12101 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | my_error(ER_INDEX_CORRUPT, MYF(0), m_prebuilt->index->name()); |
| 12102 | 12 | return HA_ERR_INDEX_CORRUPT; | |
| 12103 | } | ||
| 12104 | } else { | ||
| 12105 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | push_warning_printf(m_user_thd, Sql_condition::SL_WARNING, |
| 12106 | HA_ERR_TABLE_DEF_CHANGED, | ||
| 12107 | "InnoDB: insufficient history for index %u", keynr); | ||
| 12108 | } | ||
| 12109 | |||
| 12110 | /* The caller seems to ignore this. Thus, we must check | ||
| 12111 | this again in row_search_for_mysql(). */ | ||
| 12112 | 9 | return HA_ERR_TABLE_DEF_CHANGED; | |
| 12113 | } | ||
| 12114 | |||
| 12115 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 106895387 times.
|
106895569 | ut_a(m_prebuilt->search_tuple != nullptr); |
| 12116 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 106895512 times.
|
106895387 | ut_a(m_prebuilt->m_stop_tuple != nullptr); |
| 12117 | |||
| 12118 | /* Initialization of search_tuple is not needed for FT index | ||
| 12119 | since FT search returns rank only. In addition engine should | ||
| 12120 | be able to retrieve FTS_DOC_ID column value if necessary. */ | ||
| 12121 |
2/2✓ Branch 0 taken 1892 times.
✓ Branch 1 taken 106893620 times.
|
106895512 | if ((m_prebuilt->index->type & DICT_FTS)) { |
| 12122 |
1/2✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
|
128 | if (table->fts_doc_id_field && |
| 12123 | 128 | bitmap_is_set(table->read_set, | |
| 12124 |
4/4✓ Branch 0 taken 128 times.
✓ Branch 1 taken 1764 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1854 times.
|
2020 | table->fts_doc_id_field->field_index()) && |
| 12125 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 90 times.
|
128 | m_prebuilt->read_just_key) { |
| 12126 | 38 | m_prebuilt->fts_doc_id_in_read_set = true; | |
| 12127 | } | ||
| 12128 | } else { | ||
| 12129 |
1/2✓ Branch 0 taken 106894009 times.
✗ Branch 1 not taken.
|
106893620 | m_prebuilt->init_search_tuples_types(); |
| 12130 | |||
| 12131 | /* If it's FTS query and FTS_DOC_ID exists FTS_DOC_ID field is | ||
| 12132 | always added to read_set. */ | ||
| 12133 | 106894009 | m_prebuilt->fts_doc_id_in_read_set = | |
| 12134 |
4/4✓ Branch 0 taken 966324 times.
✓ Branch 1 taken 105927685 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 966270 times.
|
106894063 | (m_prebuilt->read_just_key && table->fts_doc_id_field && |
| 12135 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 3 times.
|
54 | m_prebuilt->in_fts_query); |
| 12136 | } | ||
| 12137 | |||
| 12138 | /* MySQL changes the active index for a handle also during some | ||
| 12139 | queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX() | ||
| 12140 | and then calculates the sum. Previously we played safe and used | ||
| 12141 | the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary | ||
| 12142 | copying. Starting from MySQL-4.1 we use a more efficient flag here. */ | ||
| 12143 | |||
| 12144 |
1/2✓ Branch 0 taken 106895712 times.
✗ Branch 1 not taken.
|
106895901 | build_template(false); |
| 12145 | |||
| 12146 | 106895712 | return 0; | |
| 12147 | 106895735 | } | |
| 12148 | |||
| 12149 | /** Reads the next or previous row from a cursor, which must have previously | ||
| 12150 | been positioned using index_read. | ||
| 12151 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 12152 | |||
| 12153 | 368042029 | int ha_innobase::general_fetch( | |
| 12154 | uchar *buf, /*!< in/out: buffer for next row in MySQL | ||
| 12155 | format */ | ||
| 12156 | uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */ | ||
| 12157 | uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or | ||
| 12158 | ROW_SEL_EXACT_PREFIX */ | ||
| 12159 | { | ||
| 12160 |
1/2✓ Branch 0 taken 368042262 times.
✗ Branch 1 not taken.
|
368042029 | DBUG_TRACE; |
| 12161 | |||
| 12162 |
8/14✓ Branch 0 taken 368042270 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 365985064 times.
✓ Branch 3 taken 2057206 times.
✓ Branch 4 taken 365985016 times.
✓ Branch 5 taken 2057246 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 365985016 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 368042262 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 368042262 times.
|
368042262 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 12163 | m_share->ib_table && m_share->ib_table->is_corrupt)) | ||
| 12164 | ✗ | return HA_ERR_CRASHED; | |
| 12165 | |||
| 12166 | 368042262 | const trx_t *trx = m_prebuilt->trx; | |
| 12167 | |||
| 12168 |
2/4✓ Branch 0 taken 368041673 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 368041866 times.
|
368042262 | ut_ad(trx == thd_to_trx(m_user_thd)); |
| 12169 | |||
| 12170 |
1/2✓ Branch 0 taken 368041839 times.
✗ Branch 1 not taken.
|
368041866 | bool intrinsic = m_prebuilt->table->is_intrinsic(); |
| 12171 | |||
| 12172 |
7/8✓ Branch 0 taken 350392466 times.
✓ Branch 1 taken 17649373 times.
✓ Branch 2 taken 350391773 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 154 times.
✓ Branch 5 taken 350391619 times.
✓ Branch 6 taken 154 times.
✓ Branch 7 taken 368040992 times.
|
368041839 | if (!intrinsic && TrxInInnoDB::is_aborted(trx)) { |
| 12173 |
1/2✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
|
154 | innobase_rollback(ht, m_user_thd, false); |
| 12174 | |||
| 12175 |
1/2✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
|
154 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); |
| 12176 | } | ||
| 12177 | |||
| 12178 |
1/2✓ Branch 0 taken 368041070 times.
✗ Branch 1 not taken.
|
368040992 | auto ret = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 12179 | |||
| 12180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 368041070 times.
|
368041070 | if (ret != DB_SUCCESS) { |
| 12181 | ✗ | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 12182 | } | ||
| 12183 | |||
| 12184 |
2/2✓ Branch 0 taken 350391702 times.
✓ Branch 1 taken 17649368 times.
|
368041070 | if (!intrinsic) { |
| 12185 |
1/2✓ Branch 0 taken 350391655 times.
✗ Branch 1 not taken.
|
350391702 | ret = row_search_mvcc(buf, PAGE_CUR_UNSUPP, m_prebuilt, match_mode, |
| 12186 | direction); | ||
| 12187 | |||
| 12188 | } else { | ||
| 12189 |
1/2✓ Branch 0 taken 17649444 times.
✗ Branch 1 not taken.
|
17649368 | ret = row_search_no_mvcc(buf, PAGE_CUR_UNSUPP, m_prebuilt, match_mode, |
| 12190 | direction); | ||
| 12191 | } | ||
| 12192 | |||
| 12193 |
1/2✓ Branch 0 taken 368041673 times.
✗ Branch 1 not taken.
|
368041099 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 12194 | |||
| 12195 | int error; | ||
| 12196 | |||
| 12197 |
4/6✓ Branch 0 taken 346108000 times.
✓ Branch 1 taken 17933623 times.
✓ Branch 2 taken 3999759 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 291 times.
|
368041673 | switch (ret) { |
| 12198 | 346108000 | case DB_SUCCESS: | |
| 12199 | 346108000 | error = 0; | |
| 12200 |
2/2✓ Branch 0 taken 207832383 times.
✓ Branch 1 taken 138275617 times.
|
346108000 | if (m_prebuilt->table->is_system_table) { |
| 12201 |
1/2✓ Branch 0 taken 207832373 times.
✗ Branch 1 not taken.
|
207832374 | srv_stats.n_system_rows_read.add( |
| 12202 |
1/2✓ Branch 0 taken 207832374 times.
✗ Branch 1 not taken.
|
207832383 | thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1); |
| 12203 | } else { | ||
| 12204 |
2/4✓ Branch 0 taken 138275684 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 138275530 times.
✗ Branch 3 not taken.
|
138275617 | srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd), |
| 12205 | 1); | ||
| 12206 | } | ||
| 12207 | 346107903 | break; | |
| 12208 | 17933623 | case DB_RECORD_NOT_FOUND: | |
| 12209 | 17933623 | error = HA_ERR_END_OF_FILE; | |
| 12210 | 17933623 | break; | |
| 12211 | 3999759 | case DB_END_OF_INDEX: | |
| 12212 | 3999759 | error = HA_ERR_END_OF_FILE; | |
| 12213 | 3999759 | break; | |
| 12214 | ✗ | case DB_TABLESPACE_DELETED: | |
| 12215 | ✗ | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, | |
| 12216 | ✗ | table->s->table_name.str); | |
| 12217 | |||
| 12218 | ✗ | error = HA_ERR_NO_SUCH_TABLE; | |
| 12219 | ✗ | break; | |
| 12220 | ✗ | case DB_TABLESPACE_NOT_FOUND: | |
| 12221 | |||
| 12222 | ✗ | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING, | |
| 12223 | ✗ | table->s->table_name.str); | |
| 12224 | |||
| 12225 | ✗ | error = HA_ERR_TABLESPACE_MISSING; | |
| 12226 | ✗ | break; | |
| 12227 | 291 | default: | |
| 12228 |
1/2✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
|
291 | error = convert_error_code_to_mysql(ret, m_prebuilt->table->flags, |
| 12229 | m_user_thd); | ||
| 12230 | |||
| 12231 | 102 | break; | |
| 12232 | } | ||
| 12233 | |||
| 12234 | 368041387 | return error; | |
| 12235 | 368041541 | } | |
| 12236 | |||
| 12237 | /** Reads the next row from a cursor, which must have previously been | ||
| 12238 | positioned using index_read. | ||
| 12239 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 12240 | |||
| 12241 | 23118236 | int ha_innobase::index_next(uchar *buf) /*!< in/out: buffer for next row in | |
| 12242 | MySQL format */ | ||
| 12243 | { | ||
| 12244 | 23118236 | ha_statistic_increment(&System_status_var::ha_read_next_count); | |
| 12245 | |||
| 12246 | 23118237 | return (general_fetch(buf, ROW_SEL_NEXT, 0)); | |
| 12247 | } | ||
| 12248 | |||
| 12249 | /** Reads the next row matching to the key value given as the parameter. | ||
| 12250 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 12251 | |||
| 12252 | 102170034 | int ha_innobase::index_next_same(uchar *buf, /*!< in/out: buffer for the row */ | |
| 12253 | const uchar *, /*!< in: key value */ | ||
| 12254 | uint) /*!< in: key value length */ | ||
| 12255 | { | ||
| 12256 | 102170034 | ha_statistic_increment(&System_status_var::ha_read_next_count); | |
| 12257 | |||
| 12258 | 102170062 | return (general_fetch(buf, ROW_SEL_NEXT, m_last_match_mode)); | |
| 12259 | } | ||
| 12260 | |||
| 12261 | /** Reads the previous row from a cursor, which must have previously been | ||
| 12262 | positioned using index_read. | ||
| 12263 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 12264 | |||
| 12265 | 19280 | int ha_innobase::index_prev( | |
| 12266 | uchar *buf) /*!< in/out: buffer for previous row in MySQL format */ | ||
| 12267 | { | ||
| 12268 | 19280 | ha_statistic_increment(&System_status_var::ha_read_prev_count); | |
| 12269 | |||
| 12270 | 19280 | return (general_fetch(buf, ROW_SEL_PREV, 0)); | |
| 12271 | } | ||
| 12272 | |||
| 12273 | /** Positions a cursor on the first record in an index and reads the | ||
| 12274 | corresponding row to buf. | ||
| 12275 | @return 0, HA_ERR_END_OF_FILE, or error code */ | ||
| 12276 | |||
| 12277 | 4831213 | int ha_innobase::index_first(uchar *buf) /*!< in/out: buffer for the row */ | |
| 12278 | { | ||
| 12279 |
1/2✓ Branch 0 taken 4831346 times.
✗ Branch 1 not taken.
|
4831213 | DBUG_TRACE; |
| 12280 | |||
| 12281 |
1/2✓ Branch 0 taken 4831352 times.
✗ Branch 1 not taken.
|
4831346 | ha_statistic_increment(&System_status_var::ha_read_first_count); |
| 12282 | |||
| 12283 |
1/2✓ Branch 0 taken 4831342 times.
✗ Branch 1 not taken.
|
4831352 | int error = index_read(buf, nullptr, 0, HA_READ_AFTER_KEY); |
| 12284 | |||
| 12285 | /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ | ||
| 12286 | |||
| 12287 |
2/2✓ Branch 0 taken 744697 times.
✓ Branch 1 taken 4086645 times.
|
4831342 | if (error == HA_ERR_KEY_NOT_FOUND) { |
| 12288 | 744697 | error = HA_ERR_END_OF_FILE; | |
| 12289 | } | ||
| 12290 | |||
| 12291 | 4831350 | return error; | |
| 12292 | 4831342 | } | |
| 12293 | |||
| 12294 | /** Positions a cursor on the last record in an index and reads the | ||
| 12295 | corresponding row to buf. | ||
| 12296 | @return 0, HA_ERR_END_OF_FILE, or error code */ | ||
| 12297 | |||
| 12298 | 14380 | int ha_innobase::index_last(uchar *buf) /*!< in/out: buffer for the row */ | |
| 12299 | { | ||
| 12300 |
1/2✓ Branch 0 taken 14380 times.
✗ Branch 1 not taken.
|
14380 | DBUG_TRACE; |
| 12301 | |||
| 12302 |
1/2✓ Branch 0 taken 14380 times.
✗ Branch 1 not taken.
|
14380 | ha_statistic_increment(&System_status_var::ha_read_last_count); |
| 12303 | |||
| 12304 |
1/2✓ Branch 0 taken 14380 times.
✗ Branch 1 not taken.
|
14380 | int error = index_read(buf, nullptr, 0, HA_READ_BEFORE_KEY); |
| 12305 | |||
| 12306 | /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ | ||
| 12307 | |||
| 12308 |
2/2✓ Branch 0 taken 4547 times.
✓ Branch 1 taken 9833 times.
|
14380 | if (error == HA_ERR_KEY_NOT_FOUND) { |
| 12309 | 4547 | error = HA_ERR_END_OF_FILE; | |
| 12310 | } | ||
| 12311 | |||
| 12312 | 14380 | return error; | |
| 12313 | 14380 | } | |
| 12314 | |||
| 12315 | 199 | int ha_innobase::sample_init(void *&scan_ctx, double sampling_percentage, | |
| 12316 | int sampling_seed, | ||
| 12317 | enum_sampling_method sampling_method, | ||
| 12318 | const bool tablesample) { | ||
| 12319 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
|
199 | ut_ad(table_share->is_missing_primary_key() == |
| 12320 | (bool)m_prebuilt->clust_index_was_generated); | ||
| 12321 | |||
| 12322 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
|
199 | ut_ad(sampling_percentage >= 0.0); |
| 12323 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
|
199 | ut_ad(sampling_percentage <= 100.0); |
| 12324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
|
199 | ut_ad(sampling_method == enum_sampling_method::SYSTEM); |
| 12325 | |||
| 12326 |
2/4✓ Branch 0 taken 199 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
|
199 | if (sampling_percentage <= 0.0 || sampling_percentage > 100.0 || |
| 12327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
|
199 | sampling_method != enum_sampling_method::SYSTEM) { |
| 12328 | ✗ | return 0; | |
| 12329 | } | ||
| 12330 | |||
| 12331 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 198 times.
|
199 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 12332 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | ib_senderrf(ha_thd(), IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, |
| 12333 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | m_prebuilt->table->name.m_name); |
| 12334 | |||
| 12335 | 1 | return HA_ERR_NO_SUCH_TABLE; | |
| 12336 | } | ||
| 12337 | |||
| 12338 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | int err = change_active_index(table_share->primary_key); |
| 12339 | |||
| 12340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | if (err != 0) { |
| 12341 | ✗ | return err; | |
| 12342 | } | ||
| 12343 | |||
| 12344 | 198 | trx_t *trx{nullptr}; | |
| 12345 | |||
| 12346 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | if (tablesample) { |
| 12347 | ✗ | update_thd(); | |
| 12348 | |||
| 12349 | ✗ | trx = m_prebuilt->trx; | |
| 12350 | ✗ | trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE); | |
| 12351 | |||
| 12352 | ✗ | if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED) { | |
| 12353 | ✗ | trx_assign_read_view(trx); | |
| 12354 | } | ||
| 12355 | } | ||
| 12356 | |||
| 12357 | /* Parallel read is not currently supported for sampling. */ | ||
| 12358 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | size_t max_threads = Parallel_reader::available_threads(1, false); |
| 12359 | |||
| 12360 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | if (max_threads == 0) { |
| 12361 | ✗ | return HA_ERR_SAMPLING_INIT_FAILED; | |
| 12362 | } | ||
| 12363 | |||
| 12364 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | Histogram_sampler *sampler = ut::new_withkey<Histogram_sampler>( |
| 12365 | 198 | UT_NEW_THIS_FILE_PSI_KEY, max_threads, sampling_seed, sampling_percentage, | |
| 12366 | sampling_method); | ||
| 12367 | |||
| 12368 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | if (sampler == nullptr) { |
| 12369 | ✗ | Parallel_reader::release_threads(max_threads); | |
| 12370 | ✗ | return HA_ERR_OUT_OF_MEM; | |
| 12371 | } | ||
| 12372 | |||
| 12373 | 198 | scan_ctx = static_cast<void *>(sampler); | |
| 12374 | |||
| 12375 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | auto index = m_prebuilt->table->first_index(); |
| 12376 | |||
| 12377 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | auto success = sampler->init(trx, index, m_prebuilt); |
| 12378 | |||
| 12379 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | if (!success) { |
| 12380 | ✗ | return (HA_ERR_SAMPLING_INIT_FAILED); | |
| 12381 | } | ||
| 12382 | |||
| 12383 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | dberr_t db_err = sampler->run(); |
| 12384 | |||
| 12385 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | if (db_err != DB_SUCCESS) { |
| 12386 | ✗ | return (convert_error_code_to_mysql(db_err, 0, ha_thd())); | |
| 12387 | } | ||
| 12388 | |||
| 12389 | 198 | return (0); | |
| 12390 | } | ||
| 12391 | |||
| 12392 | 40909 | int ha_innobase::sample_next(void *scan_ctx, uchar *buf) { | |
| 12393 | 40909 | dberr_t err = DB_SUCCESS; | |
| 12394 | |||
| 12395 | 40909 | Histogram_sampler *sampler = static_cast<Histogram_sampler *>(scan_ctx); | |
| 12396 | |||
| 12397 | 40909 | sampler->set(buf); | |
| 12398 | |||
| 12399 | /** Buffer rows one by one */ | ||
| 12400 | 40909 | err = sampler->buffer_next(); | |
| 12401 | |||
| 12402 |
2/2✓ Branch 0 taken 195 times.
✓ Branch 1 taken 40714 times.
|
40909 | if (err == DB_END_OF_INDEX) { |
| 12403 | 195 | return HA_ERR_END_OF_FILE; | |
| 12404 | } | ||
| 12405 | |||
| 12406 | 40714 | return (convert_error_code_to_mysql(err, 0, ha_thd())); | |
| 12407 | } | ||
| 12408 | |||
| 12409 | 198 | int ha_innobase::sample_end(void *scan_ctx) { | |
| 12410 | 198 | Histogram_sampler *sampler = static_cast<Histogram_sampler *>(scan_ctx); | |
| 12411 | |||
| 12412 | 198 | ut::delete_(sampler); | |
| 12413 | |||
| 12414 | 198 | return 0; | |
| 12415 | } | ||
| 12416 | |||
| 12417 | 434902 | int ha_innobase::read_range_first(const key_range *start_key, | |
| 12418 | const key_range *end_key, bool eq_range_arg, | ||
| 12419 | bool sorted) { | ||
| 12420 |
1/2✓ Branch 0 taken 434949 times.
✗ Branch 1 not taken.
|
434902 | auto guard = m_prebuilt->get_is_reading_range_guard(); |
| 12421 |
1/2✓ Branch 0 taken 435060 times.
✗ Branch 1 not taken.
|
870009 | return handler::read_range_first(start_key, end_key, eq_range_arg, sorted); |
| 12422 | 435060 | } | |
| 12423 | |||
| 12424 | 3222057 | int ha_innobase::read_range_next() { | |
| 12425 |
1/2✓ Branch 0 taken 3222057 times.
✗ Branch 1 not taken.
|
3222057 | auto guard = m_prebuilt->get_is_reading_range_guard(); |
| 12426 |
1/2✓ Branch 0 taken 3222057 times.
✗ Branch 1 not taken.
|
6444114 | return (handler::read_range_next()); |
| 12427 | 3222057 | } | |
| 12428 | |||
| 12429 | /** Initialize a table scan. | ||
| 12430 | @param[in] scan whether this is a second call to rnd_init() | ||
| 12431 | without rnd_end() in between | ||
| 12432 | @return 0 or error number */ | ||
| 12433 | 4342419 | int ha_innobase::rnd_init(bool scan) { | |
| 12434 |
1/2✓ Branch 0 taken 4342421 times.
✗ Branch 1 not taken.
|
4342419 | DBUG_TRACE; |
| 12435 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4342421 times.
|
4342421 | assert(table_share->is_missing_primary_key() == |
| 12436 | (bool)m_prebuilt->clust_index_was_generated); | ||
| 12437 | |||
| 12438 |
1/2✓ Branch 0 taken 4342420 times.
✗ Branch 1 not taken.
|
4342421 | int err = change_active_index(table_share->primary_key); |
| 12439 | |||
| 12440 | /* Don't use semi-consistent read in random row reads (by position). | ||
| 12441 | This means we must disable semi_consistent_read if scan is false */ | ||
| 12442 | |||
| 12443 |
2/2✓ Branch 0 taken 590948 times.
✓ Branch 1 taken 3751472 times.
|
4342420 | if (!scan) { |
| 12444 | 590948 | m_prebuilt->row_read_type = ROW_READ_WITH_LOCKS; | |
| 12445 | } | ||
| 12446 | |||
| 12447 | 4342420 | m_start_of_scan = true; | |
| 12448 | 4342420 | return err; | |
| 12449 | 4342420 | } | |
| 12450 | |||
| 12451 | /** Ends a table scan. | ||
| 12452 | @return 0 or error number */ | ||
| 12453 | |||
| 12454 | 2217470 | int ha_innobase::rnd_end(void) { return (index_end()); } | |
| 12455 | |||
| 12456 | /** Reads the next row in a table scan (also used to read the FIRST row | ||
| 12457 | in a table scan). | ||
| 12458 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 12459 | |||
| 12460 | 244899389 | int ha_innobase::rnd_next(uchar *buf) /*!< in/out: returns the row in this | |
| 12461 | buffer, in MySQL format */ | ||
| 12462 | { | ||
| 12463 | int error; | ||
| 12464 | |||
| 12465 |
1/2✓ Branch 0 taken 244899898 times.
✗ Branch 1 not taken.
|
244899389 | DBUG_TRACE; |
| 12466 | |||
| 12467 |
1/2✓ Branch 0 taken 244899820 times.
✗ Branch 1 not taken.
|
244899898 | ha_statistic_increment(&System_status_var::ha_read_rnd_next_count); |
| 12468 | |||
| 12469 |
2/2✓ Branch 0 taken 3751445 times.
✓ Branch 1 taken 241148375 times.
|
244899820 | if (m_start_of_scan) { |
| 12470 |
1/2✓ Branch 0 taken 3751440 times.
✗ Branch 1 not taken.
|
3751445 | error = index_first(buf); |
| 12471 | |||
| 12472 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3751440 times.
|
3751440 | if (error == HA_ERR_KEY_NOT_FOUND) { |
| 12473 | ✗ | error = HA_ERR_END_OF_FILE; | |
| 12474 | } | ||
| 12475 | |||
| 12476 | 3751440 | m_start_of_scan = false; | |
| 12477 | } else { | ||
| 12478 |
1/2✓ Branch 0 taken 241146633 times.
✗ Branch 1 not taken.
|
241148375 | error = general_fetch(buf, ROW_SEL_NEXT, 0); |
| 12479 | } | ||
| 12480 | |||
| 12481 | 244900075 | return error; | |
| 12482 | 244898073 | } | |
| 12483 | |||
| 12484 | /** Fetches a row from the table based on a row reference. | ||
| 12485 | @return 0, HA_ERR_KEY_NOT_FOUND, or error code */ | ||
| 12486 | |||
| 12487 | 8601858 | int ha_innobase::rnd_pos( | |
| 12488 | uchar *buf, /*!< in/out: buffer for the row */ | ||
| 12489 | uchar *pos) /*!< in: primary key value of the row in the | ||
| 12490 | MySQL format, or the row id if the clustered | ||
| 12491 | index was internally generated by InnoDB; the | ||
| 12492 | length of data in pos has to be ref_length */ | ||
| 12493 | { | ||
| 12494 |
1/2✓ Branch 0 taken 8601864 times.
✗ Branch 1 not taken.
|
8601858 | DBUG_TRACE; |
| 12495 |
1/2✓ Branch 0 taken 8601863 times.
✗ Branch 1 not taken.
|
8601864 | DBUG_DUMP("key", pos, ref_length); |
| 12496 | |||
| 12497 |
1/2✓ Branch 0 taken 8601863 times.
✗ Branch 1 not taken.
|
8601863 | ha_statistic_increment(&System_status_var::ha_read_rnd_count); |
| 12498 | |||
| 12499 |
3/6✓ Branch 0 taken 8601864 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8601863 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8601864 times.
|
8601863 | ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 12500 | |||
| 12501 | /* Note that we assume the length of the row reference is fixed | ||
| 12502 | for the table, and it is == ref_length */ | ||
| 12503 | |||
| 12504 |
1/2✓ Branch 0 taken 8601863 times.
✗ Branch 1 not taken.
|
8601864 | int error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT); |
| 12505 | |||
| 12506 |
2/2✓ Branch 0 taken 93 times.
✓ Branch 1 taken 8601770 times.
|
8601863 | if (error != 0) { |
| 12507 |
3/8✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 93 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
93 | DBUG_PRINT("error", ("Got error: %d", error)); |
| 12508 | } else { | ||
| 12509 | 8601770 | m_start_of_scan = false; | |
| 12510 | } | ||
| 12511 | |||
| 12512 | 8601864 | return error; | |
| 12513 | 8601863 | } | |
| 12514 | |||
| 12515 | /** Initialize FT index scan | ||
| 12516 | @return 0 or error number */ | ||
| 12517 | |||
| 12518 | 1918 | int ha_innobase::ft_init() { | |
| 12519 |
1/2✓ Branch 0 taken 1918 times.
✗ Branch 1 not taken.
|
1918 | DBUG_TRACE; |
| 12520 | |||
| 12521 |
2/4✓ Branch 0 taken 1918 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1918 times.
✗ Branch 3 not taken.
|
1918 | trx_t *trx = check_trx_exists(ha_thd()); |
| 12522 | |||
| 12523 | /* FTS queries are not treated as autocommit non-locking selects. | ||
| 12524 | This is because the FTS implementation can acquire locks behind | ||
| 12525 | the scenes. This has not been verified but it is safer to treat | ||
| 12526 | them as regular read only transactions for now. */ | ||
| 12527 | |||
| 12528 |
3/4✓ Branch 0 taken 1918 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1690 times.
✓ Branch 3 taken 228 times.
|
1918 | if (!trx_is_started(trx)) { |
| 12529 | 1690 | ++trx->will_lock; | |
| 12530 | } | ||
| 12531 | |||
| 12532 |
1/2✓ Branch 0 taken 1918 times.
✗ Branch 1 not taken.
|
3836 | return rnd_init(false); |
| 12533 | 1918 | } | |
| 12534 | |||
| 12535 | /** Initialize FT index scan | ||
| 12536 | @return FT_INFO structure if successful or NULL */ | ||
| 12537 | |||
| 12538 | 2295 | FT_INFO *ha_innobase::ft_init_ext(uint flags, /* in: */ | |
| 12539 | uint keynr, /* in: */ | ||
| 12540 | String *key) /* in: */ | ||
| 12541 | { | ||
| 12542 | 2295 | NEW_FT_INFO *fts_hdl = nullptr; | |
| 12543 | dict_index_t *index; | ||
| 12544 | fts_result_t *result; | ||
| 12545 | char buf_tmp[8192]; | ||
| 12546 | ulint buf_tmp_used; | ||
| 12547 | uint num_errors; | ||
| 12548 | 2295 | ulint query_len = key->length(); | |
| 12549 | 2295 | const CHARSET_INFO *char_set = key->charset(); | |
| 12550 | 2295 | const char *query = key->ptr(); | |
| 12551 | |||
| 12552 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 2257 times.
|
2295 | if (fts_enable_diag_print) { |
| 12553 | { | ||
| 12554 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | ib::info out(ER_IB_MSG_1220); |
| 12555 |
3/6✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
|
38 | out << "keynr=" << keynr << ", '"; |
| 12556 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | out.write(key->ptr(), key->length()); |
| 12557 | 38 | } | |
| 12558 | |||
| 12559 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 6 times.
|
38 | if (flags & FT_BOOL) { |
| 12560 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
|
32 | ib::info(ER_IB_MSG_562) << "BOOL search"; |
| 12561 | } else { | ||
| 12562 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | ib::info(ER_IB_MSG_563) << "NL search"; |
| 12563 | } | ||
| 12564 | } | ||
| 12565 | |||
| 12566 | /* FIXME: utf32 and utf16 are not compatible with some | ||
| 12567 | string function used. So to convert them to uft8 before | ||
| 12568 | we proceed. */ | ||
| 12569 |
1/2✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
|
2295 | if (strcmp(char_set->csname, "utf32") == 0 || |
| 12570 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2295 times.
|
2295 | strcmp(char_set->csname, "utf16") == 0) { |
| 12571 | ✗ | buf_tmp_used = innobase_convert_string( | |
| 12572 | buf_tmp, sizeof(buf_tmp) - 1, &my_charset_utf8_general_ci, query, | ||
| 12573 | query_len, (CHARSET_INFO *)char_set, &num_errors); | ||
| 12574 | |||
| 12575 | ✗ | buf_tmp[buf_tmp_used] = 0; | |
| 12576 | ✗ | query = buf_tmp; | |
| 12577 | ✗ | query_len = buf_tmp_used; | |
| 12578 | } | ||
| 12579 | |||
| 12580 | 2295 | trx_t *trx = m_prebuilt->trx; | |
| 12581 | |||
| 12582 |
1/2✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
|
2295 | TrxInInnoDB trx_in_innodb(trx); |
| 12583 | |||
| 12584 |
2/4✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2295 times.
|
2295 | if (trx_in_innodb.is_aborted()) { |
| 12585 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 12586 | |||
| 12587 | int err; | ||
| 12588 | ✗ | err = convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 12589 | |||
| 12590 | ✗ | my_error(err, MYF(0)); | |
| 12591 | |||
| 12592 | ✗ | return (nullptr); | |
| 12593 | } | ||
| 12594 | |||
| 12595 | /* FTS queries are not treated as autocommit non-locking selects. | ||
| 12596 | This is because the FTS implementation can acquire locks behind | ||
| 12597 | the scenes. This has not been verified but it is safer to treat | ||
| 12598 | them as regular read only transactions for now. */ | ||
| 12599 | |||
| 12600 |
3/4✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2123 times.
✓ Branch 3 taken 172 times.
|
2295 | if (!trx_is_started(trx)) { |
| 12601 | 2123 | ++trx->will_lock; | |
| 12602 | } | ||
| 12603 | |||
| 12604 | 2295 | dict_table_t *ft_table = m_prebuilt->table; | |
| 12605 | |||
| 12606 | /* Table does not have an FTS index */ | ||
| 12607 |
3/6✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2295 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2295 times.
|
2295 | if (!ft_table->fts || ib_vector_is_empty(ft_table->fts->indexes)) { |
| 12608 | ✗ | my_error(ER_TABLE_HAS_NO_FT, MYF(0)); | |
| 12609 | ✗ | return (nullptr); | |
| 12610 | } | ||
| 12611 | |||
| 12612 | /* If tablespace is discarded, we should return here */ | ||
| 12613 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2295 times.
|
2295 | if (dict_table_is_discarded(ft_table)) { |
| 12614 | ✗ | my_error(ER_NO_SUCH_TABLE, MYF(0), table->s->db.str, | |
| 12615 | ✗ | table->s->table_name.str); | |
| 12616 | ✗ | return (nullptr); | |
| 12617 | } | ||
| 12618 | |||
| 12619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2295 times.
|
2295 | if (keynr == NO_SUCH_KEY) { |
| 12620 | /* FIXME: Investigate the NO_SUCH_KEY usage */ | ||
| 12621 | ✗ | index = reinterpret_cast<dict_index_t *>( | |
| 12622 | ✗ | ib_vector_getp(ft_table->fts->indexes, 0)); | |
| 12623 | } else { | ||
| 12624 |
1/2✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
|
2295 | index = innobase_get_index(keynr); |
| 12625 | } | ||
| 12626 | |||
| 12627 |
3/4✓ Branch 0 taken 2295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2294 times.
|
2295 | if (index == nullptr || index->type != DICT_FTS) { |
| 12628 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error(ER_TABLE_HAS_NO_FT, MYF(0)); |
| 12629 | 1 | return (nullptr); | |
| 12630 | } | ||
| 12631 | |||
| 12632 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2241 times.
|
2294 | if (!(ft_table->fts->fts_status & ADDED_TABLE_SYNCED)) { |
| 12633 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
53 | fts_init_index(ft_table, false); |
| 12634 | |||
| 12635 | 53 | ft_table->fts->fts_status |= ADDED_TABLE_SYNCED; | |
| 12636 | } | ||
| 12637 | |||
| 12638 | 2294 | const byte *q = reinterpret_cast<const byte *>(const_cast<char *>(query)); | |
| 12639 | |||
| 12640 | 4588 | dberr_t error = fts_query(trx, index, flags, q, query_len, &result, | |
| 12641 |
1/2✓ Branch 0 taken 2294 times.
✗ Branch 1 not taken.
|
2294 | m_prebuilt->m_fts_limit); |
| 12642 | |||
| 12643 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2288 times.
|
2294 | if (error != DB_SUCCESS) { |
| 12644 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | my_error(convert_error_code_to_mysql(error, 0, nullptr), MYF(0)); |
| 12645 | 6 | return (nullptr); | |
| 12646 | } | ||
| 12647 | |||
| 12648 | /* Allocate FTS handler, and instantiate it before return */ | ||
| 12649 | fts_hdl = reinterpret_cast<NEW_FT_INFO *>( | ||
| 12650 |
1/2✓ Branch 0 taken 2288 times.
✗ Branch 1 not taken.
|
2288 | my_malloc(PSI_INSTRUMENT_ME, sizeof(NEW_FT_INFO), MYF(0))); |
| 12651 | |||
| 12652 | 2288 | fts_hdl->please = const_cast<_ft_vft *>(&ft_vft_result); | |
| 12653 | 2288 | fts_hdl->could_you = const_cast<_ft_vft_ext *>(&ft_vft_ext_result); | |
| 12654 | 2288 | fts_hdl->ft_prebuilt = m_prebuilt; | |
| 12655 | 2288 | fts_hdl->ft_result = result; | |
| 12656 | |||
| 12657 | /* FIXME: Re-evaluate the condition when Bug 14469540 is resolved */ | ||
| 12658 | 2288 | m_prebuilt->in_fts_query = true; | |
| 12659 | |||
| 12660 | 2288 | return (reinterpret_cast<FT_INFO *>(fts_hdl)); | |
| 12661 | 2295 | } | |
| 12662 | |||
| 12663 | /** Initialize FT index scan | ||
| 12664 | @return FT_INFO structure if successful or NULL */ | ||
| 12665 | |||
| 12666 | 2295 | FT_INFO *ha_innobase::ft_init_ext_with_hints(uint keynr, /* in: key num */ | |
| 12667 | String *key, /* in: key */ | ||
| 12668 | Ft_hints *hints) /* in: hints */ | ||
| 12669 | { | ||
| 12670 | /* TODO Implement function properly working with FT hint. */ | ||
| 12671 |
2/2✓ Branch 0 taken 1275 times.
✓ Branch 1 taken 1020 times.
|
2295 | if (hints->get_flags() & FT_NO_RANKING) { |
| 12672 | 1275 | m_prebuilt->m_fts_limit = hints->get_limit(); | |
| 12673 | } else { | ||
| 12674 | 1020 | m_prebuilt->m_fts_limit = ULONG_UNDEFINED; | |
| 12675 | } | ||
| 12676 | |||
| 12677 | 2295 | return (ft_init_ext(hints->get_flags(), keynr, key)); | |
| 12678 | } | ||
| 12679 | |||
| 12680 | /** Set up search tuple for a query through FTS_DOC_ID_INDEX on | ||
| 12681 | supplied Doc ID. This is used by MySQL to retrieve the documents | ||
| 12682 | once the search result (Doc IDs) is available */ | ||
| 12683 | 36648 | static void innobase_fts_create_doc_id_key( | |
| 12684 | dtuple_t *tuple, /* in/out: m_prebuilt->search_tuple */ | ||
| 12685 | const dict_index_t *index, /* in: index (FTS_DOC_ID_INDEX) */ | ||
| 12686 | doc_id_t *doc_id) /* in/out: doc id to search, value | ||
| 12687 | could be changed to storage format | ||
| 12688 | used for search. */ | ||
| 12689 | { | ||
| 12690 | doc_id_t temp_doc_id; | ||
| 12691 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | dfield_t *dfield = dtuple_get_nth_field(tuple, 0); |
| 12692 | |||
| 12693 |
2/4✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 36648 times.
|
36648 | ut_a(dict_index_get_n_unique(index) == 1); |
| 12694 | |||
| 12695 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | dtuple_set_n_fields(tuple, index->n_fields); |
| 12696 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | dict_index_copy_types(tuple, index, index->n_fields); |
| 12697 | |||
| 12698 | #ifdef UNIV_DEBUG | ||
| 12699 | /* The unique Doc ID field should be an eight-bytes integer */ | ||
| 12700 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | dict_field_t *field = index->get_field(0); |
| 12701 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36648 times.
|
36648 | ut_a(field->col->mtype == DATA_INT); |
| 12702 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36648 times.
|
36648 | ut_ad(sizeof(*doc_id) == field->fixed_len); |
| 12703 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36648 times.
|
36648 | ut_ad(!strcmp(index->name, FTS_DOC_ID_INDEX_NAME)); |
| 12704 | #endif /* UNIV_DEBUG */ | ||
| 12705 | |||
| 12706 | /* Convert to storage byte order */ | ||
| 12707 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | mach_write_to_8(reinterpret_cast<byte *>(&temp_doc_id), *doc_id); |
| 12708 | 36648 | *doc_id = temp_doc_id; | |
| 12709 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | dfield_set_data(dfield, doc_id, sizeof(*doc_id)); |
| 12710 | |||
| 12711 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | dtuple_set_n_fields_cmp(tuple, 1); |
| 12712 | |||
| 12713 |
2/2✓ Branch 0 taken 36384 times.
✓ Branch 1 taken 36648 times.
|
73032 | for (ulint i = 1; i < index->n_fields; i++) { |
| 12714 |
1/2✓ Branch 0 taken 36384 times.
✗ Branch 1 not taken.
|
36384 | dfield = dtuple_get_nth_field(tuple, i); |
| 12715 |
1/2✓ Branch 0 taken 36384 times.
✗ Branch 1 not taken.
|
36384 | dfield_set_null(dfield); |
| 12716 | } | ||
| 12717 | 36648 | } | |
| 12718 | |||
| 12719 | /** Fetch next result from the FT result set | ||
| 12720 | @return error code */ | ||
| 12721 | |||
| 12722 | 38636 | int ha_innobase::ft_read(uchar *buf) /*!< in/out: buf contain result row */ | |
| 12723 | { | ||
| 12724 |
1/2✓ Branch 0 taken 38636 times.
✗ Branch 1 not taken.
|
38636 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 12725 | |||
| 12726 |
2/4✓ Branch 0 taken 38636 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 38636 times.
|
38636 | if (trx_in_innodb.is_aborted()) { |
| 12727 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 12728 | |||
| 12729 | ✗ | return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd)); | |
| 12730 | } | ||
| 12731 | |||
| 12732 | row_prebuilt_t *ft_prebuilt; | ||
| 12733 | |||
| 12734 | 38636 | ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(ft_handler)->ft_prebuilt; | |
| 12735 | |||
| 12736 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38636 times.
|
38636 | ut_a(ft_prebuilt == m_prebuilt); |
| 12737 | |||
| 12738 | fts_result_t *result; | ||
| 12739 | |||
| 12740 | 38636 | result = reinterpret_cast<NEW_FT_INFO *>(ft_handler)->ft_result; | |
| 12741 | |||
| 12742 |
2/2✓ Branch 0 taken 1907 times.
✓ Branch 1 taken 36729 times.
|
38636 | if (result->current == nullptr) { |
| 12743 | /* This is the case where the FTS query did not | ||
| 12744 | contain and matching documents. */ | ||
| 12745 |
2/2✓ Branch 0 taken 1416 times.
✓ Branch 1 taken 491 times.
|
1907 | if (result->rankings_by_id != nullptr) { |
| 12746 | /* Now that we have the complete result, we | ||
| 12747 | need to sort the document ids on their rank | ||
| 12748 | calculation. */ | ||
| 12749 | |||
| 12750 |
1/2✓ Branch 0 taken 1416 times.
✗ Branch 1 not taken.
|
1416 | fts_query_sort_result_on_rank(result); |
| 12751 | |||
| 12752 | 1416 | result->current = | |
| 12753 |
1/2✓ Branch 0 taken 1416 times.
✗ Branch 1 not taken.
|
1416 | const_cast<ib_rbt_node_t *>(rbt_first(result->rankings_by_rank)); |
| 12754 | } else { | ||
| 12755 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
|
491 | ut_a(result->current == nullptr); |
| 12756 | } | ||
| 12757 | } else { | ||
| 12758 | 36729 | result->current = const_cast<ib_rbt_node_t *>( | |
| 12759 |
1/2✓ Branch 0 taken 36729 times.
✗ Branch 1 not taken.
|
36729 | rbt_next(result->rankings_by_rank, result->current)); |
| 12760 | } | ||
| 12761 | |||
| 12762 | 38636 | next_record: | |
| 12763 | |||
| 12764 |
2/2✓ Branch 0 taken 36782 times.
✓ Branch 1 taken 1858 times.
|
38640 | if (result->current != nullptr) { |
| 12765 | doc_id_t search_doc_id; | ||
| 12766 | 36782 | dtuple_t *tuple = m_prebuilt->search_tuple; | |
| 12767 | |||
| 12768 | /* If we only need information from result we can return | ||
| 12769 | without fetching the table row */ | ||
| 12770 |
2/2✓ Branch 0 taken 134 times.
✓ Branch 1 taken 36648 times.
|
36782 | if (ft_prebuilt->read_just_key) { |
| 12771 | 134 | const fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current); | |
| 12772 | 134 | m_prebuilt->fts_doc_id = ranking->doc_id; | |
| 12773 |
1/2✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
|
134 | if (m_prebuilt->fts_doc_id_in_read_set) { |
| 12774 |
1/2✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
|
134 | innobase_fts_store_docid(table, ranking->doc_id); |
| 12775 | } | ||
| 12776 | 36778 | return (0); | |
| 12777 | } | ||
| 12778 | |||
| 12779 | dict_index_t *index; | ||
| 12780 | |||
| 12781 | 36648 | index = m_prebuilt->table->fts_doc_id_index; | |
| 12782 | |||
| 12783 | /* Must find the index */ | ||
| 12784 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36648 times.
|
36648 | ut_a(index != nullptr); |
| 12785 | |||
| 12786 | /* Switch to the FTS doc id index */ | ||
| 12787 | 36648 | m_prebuilt->index = index; | |
| 12788 | |||
| 12789 | 36648 | fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current); | |
| 12790 | |||
| 12791 | 36648 | search_doc_id = ranking->doc_id; | |
| 12792 | |||
| 12793 | /* We pass a pointer of search_doc_id because it will be | ||
| 12794 | converted to storage byte order used in the search | ||
| 12795 | tuple. */ | ||
| 12796 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | innobase_fts_create_doc_id_key(tuple, index, &search_doc_id); |
| 12797 | |||
| 12798 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | auto ret = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 12799 | |||
| 12800 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | if (ret == DB_SUCCESS) { |
| 12801 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | ret = row_search_for_mysql((byte *)buf, PAGE_CUR_GE, m_prebuilt, |
| 12802 | ROW_SEL_EXACT, 0); | ||
| 12803 |
1/2✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
|
36648 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 12804 | } | ||
| 12805 | |||
| 12806 | int error; | ||
| 12807 | |||
| 12808 |
6/14✓ Branch 0 taken 36648 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36648 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36648 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 36648 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 36648 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 36648 times.
|
36648 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 12809 | m_share->ib_table && m_share->ib_table->is_corrupt)) { | ||
| 12810 | ✗ | return (HA_ERR_CRASHED); | |
| 12811 | } | ||
| 12812 | |||
| 12813 |
2/6✓ Branch 0 taken 36632 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
36648 | switch (ret) { |
| 12814 | 36632 | case DB_SUCCESS: | |
| 12815 | 36632 | error = 0; | |
| 12816 | 36632 | break; | |
| 12817 | 16 | case DB_RECORD_NOT_FOUND: | |
| 12818 | 16 | result->current = const_cast<ib_rbt_node_t *>( | |
| 12819 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | rbt_next(result->rankings_by_rank, result->current)); |
| 12820 | |||
| 12821 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
|
16 | if (!result->current) { |
| 12822 | /* exhaust the result set, should return | ||
| 12823 | HA_ERR_END_OF_FILE just like | ||
| 12824 | ha_innobase::general_fetch() and/or | ||
| 12825 | ha_innobase::index_first() etc. */ | ||
| 12826 | 12 | error = HA_ERR_END_OF_FILE; | |
| 12827 | } else { | ||
| 12828 | 4 | goto next_record; | |
| 12829 | } | ||
| 12830 | 12 | break; | |
| 12831 | ✗ | case DB_END_OF_INDEX: | |
| 12832 | ✗ | error = HA_ERR_END_OF_FILE; | |
| 12833 | ✗ | break; | |
| 12834 | ✗ | case DB_TABLESPACE_DELETED: | |
| 12835 | |||
| 12836 | ✗ | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 12837 | ✗ | ER_TABLESPACE_DISCARDED, table->s->table_name.str); | |
| 12838 | |||
| 12839 | ✗ | error = HA_ERR_NO_SUCH_TABLE; | |
| 12840 | ✗ | break; | |
| 12841 | ✗ | case DB_TABLESPACE_NOT_FOUND: | |
| 12842 | |||
| 12843 | ✗ | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 12844 | ✗ | ER_TABLESPACE_MISSING, table->s->table_name.str); | |
| 12845 | |||
| 12846 | ✗ | error = HA_ERR_TABLESPACE_MISSING; | |
| 12847 | ✗ | break; | |
| 12848 | ✗ | default: | |
| 12849 | ✗ | error = convert_error_code_to_mysql(ret, 0, m_user_thd); | |
| 12850 | |||
| 12851 | ✗ | break; | |
| 12852 | } | ||
| 12853 | |||
| 12854 | 36644 | return (error); | |
| 12855 | } | ||
| 12856 | |||
| 12857 | 1858 | return (HA_ERR_END_OF_FILE); | |
| 12858 | 38636 | } | |
| 12859 | |||
| 12860 | /************************************************************************* | ||
| 12861 | */ | ||
| 12862 | |||
| 12863 | ✗ | void ha_innobase::ft_end() { | |
| 12864 | ✗ | ib::info(ER_IB_MSG_564) << "ft_end()"; | |
| 12865 | |||
| 12866 | ✗ | rnd_end(); | |
| 12867 | } | ||
| 12868 | |||
| 12869 | #ifdef WITH_WSREP | ||
| 12870 | dict_index_t *wsrep_dict_foreign_find_index(dict_table_t *table, | ||
| 12871 | const char **col_names, | ||
| 12872 | const char **columns, ulint n_cols, | ||
| 12873 | dict_index_t *types_idx, | ||
| 12874 | bool check_charsets, | ||
| 12875 | ulint check_null); | ||
| 12876 | |||
| 12877 | ✗ | inline const char *wsrep_key_type_to_str(Wsrep_service_key_type type) { | |
| 12878 | ✗ | switch (type) { | |
| 12879 | ✗ | case WSREP_SERVICE_KEY_SHARED: | |
| 12880 | ✗ | return "shared"; | |
| 12881 | ✗ | case WSREP_SERVICE_KEY_REFERENCE: | |
| 12882 | ✗ | return "reference"; | |
| 12883 | ✗ | case WSREP_SERVICE_KEY_UPDATE: | |
| 12884 | ✗ | return "update"; | |
| 12885 | ✗ | case WSREP_SERVICE_KEY_EXCLUSIVE: | |
| 12886 | ✗ | return "exclusive"; | |
| 12887 | }; | ||
| 12888 | ✗ | return "unknown"; | |
| 12889 | } | ||
| 12890 | |||
| 12891 | 319745 | extern dberr_t wsrep_append_foreign_key( | |
| 12892 | trx_t *trx, /*!< in: trx */ | ||
| 12893 | dict_foreign_t *foreign, /*!< in: foreign key constraint */ | ||
| 12894 | const rec_t *rec, /*!< in: clustered index record */ | ||
| 12895 | dict_index_t *index, /*!< in: clustered index */ | ||
| 12896 | bool referenced, /*!< in: is check for referenced table */ | ||
| 12897 | Wsrep_service_key_type key_type) /*!< in: access type of this key | ||
| 12898 | (shared, exclusive, reference...) */ | ||
| 12899 | { | ||
| 12900 | 319745 | THD *thd = (THD *)trx->mysql_thd; | |
| 12901 | 319745 | int rcode = 0; | |
| 12902 | 319745 | char cache_key[513] = {'\0'}; | |
| 12903 | int cache_key_len; | ||
| 12904 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 319745 times.
|
319745 | ut_a(trx); |
| 12905 | |||
| 12906 |
3/4✓ Branch 0 taken 319745 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 305643 times.
✓ Branch 3 taken 14102 times.
|
319745 | if (!wsrep_do_replication(thd)) { |
| 12907 | 305643 | return DB_SUCCESS; | |
| 12908 | } | ||
| 12909 | |||
| 12910 |
2/4✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14102 times.
✗ Branch 3 not taken.
|
14102 | if (!thd || !foreign || |
| 12911 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 14102 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
14102 | (!foreign->referenced_table && !foreign->foreign_table)) { |
| 12912 | ✗ | WSREP_INFO("FK: %s missing in: %s", | |
| 12913 | (!thd) ? "thread" | ||
| 12914 | : ((!foreign) ? "constraint" | ||
| 12915 | : ((!foreign->referenced_table) | ||
| 12916 | ? "referenced table" | ||
| 12917 | : "foreign table")), | ||
| 12918 | (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); | ||
| 12919 | ✗ | return DB_ERROR; | |
| 12920 | } | ||
| 12921 | |||
| 12922 |
3/4✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14102 times.
|
14102 | if (!((referenced) ? foreign->referenced_table : foreign->foreign_table)) { |
| 12923 | ✗ | WSREP_DEBUG("pulling %s table into cache", | |
| 12924 | (referenced) ? "referenced" : "foreign"); | ||
| 12925 | ✗ | mutex_enter(&(dict_sys->mutex)); | |
| 12926 | ✗ | if (referenced) { | |
| 12927 | ✗ | foreign->referenced_table = | |
| 12928 | ✗ | dict_table_get_low(foreign->referenced_table_name_lookup); | |
| 12929 | ✗ | if (foreign->referenced_table) { | |
| 12930 | ✗ | foreign->referenced_index = wsrep_dict_foreign_find_index( | |
| 12931 | foreign->referenced_table, NULL, foreign->referenced_col_names, | ||
| 12932 | ✗ | foreign->n_fields, foreign->foreign_index, true, false); | |
| 12933 | } | ||
| 12934 | } else { | ||
| 12935 | ✗ | foreign->foreign_table = | |
| 12936 | ✗ | dict_table_get_low(foreign->foreign_table_name_lookup); | |
| 12937 | ✗ | if (foreign->foreign_table) { | |
| 12938 | ✗ | foreign->foreign_index = wsrep_dict_foreign_find_index( | |
| 12939 | foreign->foreign_table, NULL, foreign->foreign_col_names, | ||
| 12940 | ✗ | foreign->n_fields, foreign->referenced_index, true, false); | |
| 12941 | } | ||
| 12942 | } | ||
| 12943 | ✗ | mutex_exit(&(dict_sys->mutex)); | |
| 12944 | } | ||
| 12945 | |||
| 12946 |
3/4✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14102 times.
|
14102 | if (!((referenced) ? foreign->referenced_table : foreign->foreign_table)) { |
| 12947 | ✗ | WSREP_WARN( | |
| 12948 | "FK: %s missing in query: %s", | ||
| 12949 | (!foreign->referenced_table) ? "referenced table" : "foreign table", | ||
| 12950 | (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); | ||
| 12951 | ✗ | return DB_ERROR; | |
| 12952 | } | ||
| 12953 | 14102 | byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH + 1] = {'\0'}; | |
| 12954 | 14102 | ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; | |
| 12955 | |||
| 12956 |
2/2✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
|
14102 | dict_index_t *idx_target = (referenced) ? foreign->referenced_index : index; |
| 12957 | 14102 | dict_index_t *idx = | |
| 12958 |
2/2✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
|
14102 | (referenced) ? UT_LIST_GET_FIRST(foreign->referenced_table->indexes) |
| 12959 | 10072 | : UT_LIST_GET_FIRST(foreign->foreign_table->indexes); | |
| 12960 | 14102 | int i = 0; | |
| 12961 |
3/4✓ Branch 0 taken 14126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 14102 times.
|
14126 | while (idx != NULL && idx != idx_target) { |
| 12962 |
3/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 17 times.
|
24 | if (innobase_strcasecmp(idx->name, innobase_index_reserve_name) != 0) { |
| 12963 | 7 | i++; | |
| 12964 | } | ||
| 12965 | 24 | idx = UT_LIST_GET_NEXT(indexes, idx); | |
| 12966 | } | ||
| 12967 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14102 times.
|
14102 | ut_a(idx); |
| 12968 | 14102 | key[0] = (char)i; | |
| 12969 | |||
| 12970 |
1/2✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
|
14102 | rcode = wsrep_rec_get_foreign_key(&key[1], &len, rec, index, idx, |
| 12971 | wsrep_protocol_version > 1); | ||
| 12972 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14102 times.
|
14102 | if (rcode != DB_SUCCESS) { |
| 12973 | ✗ | WSREP_ERROR( | |
| 12974 | "FK key set failed: %d (%d %s), index: %s %s, %s", rcode, referenced, | ||
| 12975 | wsrep_key_type_to_str(key_type), | ||
| 12976 | (index && index->name) ? (const char *)(index->name) : "void index", | ||
| 12977 | (index && index->table_name) ? (index->table_name) : "void table", | ||
| 12978 | wsrep_thd_query(thd)); | ||
| 12979 | ✗ | return DB_ERROR; | |
| 12980 | } | ||
| 12981 |
2/2✓ Branch 0 taken 4030 times.
✓ Branch 1 taken 10072 times.
|
28204 | strncpy(cache_key, |
| 12982 |
1/2✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
|
14102 | (wsrep_protocol_version > 1) |
| 12983 | 4030 | ? ((referenced) ? foreign->referenced_table->name.m_name | |
| 12984 | 10072 | : foreign->foreign_table->name.m_name) | |
| 12985 | ✗ | : foreign->foreign_table->name.m_name, | |
| 12986 | sizeof(cache_key) - 1); | ||
| 12987 | 14102 | cache_key_len = strlen(cache_key); | |
| 12988 | #ifdef WSREP_DEBUG_PRINT | ||
| 12989 | ulint j; | ||
| 12990 | fprintf(stderr, "FK parent key, table: %s %s len: %lu ", cache_key, | ||
| 12991 | wsrep_key_type_to_str(key_type), len + 1); | ||
| 12992 | for (j = 0; j < len + 1; j++) { | ||
| 12993 | fprintf(stderr, " %hhX, ", key[j]); | ||
| 12994 | } | ||
| 12995 | fprintf(stderr, "\n"); | ||
| 12996 | #endif /* WSREP_DEBUG_PRINT */ | ||
| 12997 | 14102 | char *p = strchr(cache_key, '/'); | |
| 12998 |
1/2✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
|
14102 | if (p) { |
| 12999 | 14102 | *p = '\0'; | |
| 13000 | } else { | ||
| 13001 | ✗ | WSREP_WARN("unexpected foreign key table %s %s", | |
| 13002 | foreign->referenced_table->name.m_name, | ||
| 13003 | foreign->foreign_table->name.m_name); | ||
| 13004 | } | ||
| 13005 | |||
| 13006 | wsrep_buf_t wkey_part[3]; | ||
| 13007 | 14102 | wsrep_key_t wkey = {wkey_part, 3}; | |
| 13008 |
2/4✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14102 times.
|
14102 | if (!wsrep_prepare_key_for_innodb((const uchar *)cache_key, cache_key_len + 1, |
| 13009 | (const uchar *)key, len + 1, wkey_part, | ||
| 13010 | &wkey.key_parts_num)) { | ||
| 13011 | ✗ | WSREP_WARN("key prepare failed for cascaded FK: %s", | |
| 13012 | (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); | ||
| 13013 | ✗ | return DB_ERROR; | |
| 13014 | } | ||
| 13015 |
1/2✓ Branch 0 taken 14102 times.
✗ Branch 1 not taken.
|
14102 | rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type); |
| 13016 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14102 times.
|
14102 | if (rcode) { |
| 13017 | ✗ | DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); | |
| 13018 | ✗ | WSREP_ERROR("Appending cascaded fk row key failed: %s, %d", | |
| 13019 | (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", rcode); | ||
| 13020 | ✗ | return DB_ERROR; | |
| 13021 | } | ||
| 13022 | |||
| 13023 | 14102 | return DB_SUCCESS; | |
| 13024 | } | ||
| 13025 | |||
| 13026 | 3832404 | static int wsrep_append_key( | |
| 13027 | THD *thd, trx_t *trx, TABLE_SHARE *table_share, const char *key, | ||
| 13028 | uint16_t key_len, | ||
| 13029 | Wsrep_service_key_type key_type /*!< in: access type of this key | ||
| 13030 | (shared, exclusive, semi...) */ | ||
| 13031 | ) { | ||
| 13032 |
1/2✓ Branch 0 taken 3832404 times.
✗ Branch 1 not taken.
|
3832404 | DBUG_ENTER("wsrep_append_key"); |
| 13033 | #ifdef WSREP_DEBUG_PRINT | ||
| 13034 | if (wsrep_debug) { | ||
| 13035 | fprintf(stderr, "%s conn %lu, trx %llu, keylen %d, table %s\n SQL: %s ", | ||
| 13036 | wsrep_key_type_to_str(key_type), wsrep_thd_thread_id(thd), | ||
| 13037 | (long long)trx->id, key_len, table_share->table_name.str, | ||
| 13038 | wsrep_thd_query(thd)); | ||
| 13039 | for (int i = 0; i < key_len; i++) { | ||
| 13040 | fprintf(stderr, "%hhX, ", key[i]); | ||
| 13041 | } | ||
| 13042 | fprintf(stderr, "\n"); | ||
| 13043 | } | ||
| 13044 | #endif /* WSREP_DEBUG_PRINT */ | ||
| 13045 | wsrep_buf_t wkey_part[3]; | ||
| 13046 | 3832404 | wsrep_key_t wkey = {wkey_part, 3}; | |
| 13047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3832404 times.
|
3832404 | if (!wsrep_prepare_key_for_innodb( |
| 13048 |
1/2✓ Branch 0 taken 3832404 times.
✗ Branch 1 not taken.
|
3832404 | (const uchar *)table_share->table_cache_key.str, |
| 13049 | table_share->table_cache_key.length, (const uchar *)key, key_len, | ||
| 13050 | wkey_part, &wkey.key_parts_num)) { | ||
| 13051 | ✗ | WSREP_WARN("key prepare failed for: %s", | |
| 13052 | (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); | ||
| 13053 | ✗ | DBUG_RETURN(-1); | |
| 13054 | } | ||
| 13055 | |||
| 13056 |
1/2✓ Branch 0 taken 3832404 times.
✗ Branch 1 not taken.
|
3832404 | int rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type); |
| 13057 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3832403 times.
|
3832404 | if (rcode) { |
| 13058 |
3/8✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
1 | DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); |
| 13059 |
13/28✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
|
1 | WSREP_WARN("Appending row key failed: %s, %d", |
| 13060 | (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", rcode); | ||
| 13061 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | DBUG_RETURN(-1); |
| 13062 | } | ||
| 13063 |
1/2✓ Branch 0 taken 3832403 times.
✗ Branch 1 not taken.
|
3832403 | DBUG_RETURN(0); |
| 13064 | } | ||
| 13065 | |||
| 13066 | extern int compute_md5_hash(char *digest, const char *buf, int len); | ||
| 13067 | #define MD5_HASH compute_md5_hash | ||
| 13068 | |||
| 13069 | 15122 | bool wsrep_is_FK_index(dict_table_t *table, dict_index_t *index) { | |
| 13070 | 15122 | const dict_foreign_set *fks = &table->referenced_set; | |
| 13071 | |||
| 13072 | /* Check for all FK references from other tables to the index. */ | ||
| 13073 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 15115 times.
|
15136 | for (dict_foreign_set::const_iterator it = fks->begin(); it != fks->end(); |
| 13074 | 14 | ++it) { | |
| 13075 | 21 | dict_foreign_t *foreign = *it; | |
| 13076 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 14 times.
|
21 | if (foreign->referenced_index == index) { |
| 13077 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | ut_ad(table == foreign->referenced_table); |
| 13078 | 7 | return true; | |
| 13079 | } | ||
| 13080 | } | ||
| 13081 | 15115 | return false; | |
| 13082 | } | ||
| 13083 | |||
| 13084 | 4343913 | int ha_innobase::wsrep_append_keys( | |
| 13085 | THD *thd, /*!< in: thread handler */ | ||
| 13086 | Wsrep_service_key_type key_type, /*!< in: access type of this key | ||
| 13087 | (shared, exclusive, reference...) */ | ||
| 13088 | const uchar *record0, /* in: row in MySQL format */ | ||
| 13089 | const uchar *record1) /* in: row in MySQL format */ | ||
| 13090 | { | ||
| 13091 | /* Sanity check: newly inserted records should always be passed with | ||
| 13092 | EXCLUSIVE key type, all the rest are expected to carry a pre-image | ||
| 13093 | */ | ||
| 13094 |
4/6✓ Branch 0 taken 3723050 times.
✓ Branch 1 taken 620863 times.
✓ Branch 2 taken 3723050 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4343913 times.
|
4343913 | ut_a(record1 != NULL || key_type == WSREP_SERVICE_KEY_EXCLUSIVE); |
| 13095 | |||
| 13096 | int rcode; | ||
| 13097 |
1/2✓ Branch 0 taken 4343913 times.
✗ Branch 1 not taken.
|
4343913 | DBUG_ENTER("wsrep_append_keys"); |
| 13098 | |||
| 13099 | 4343913 | bool key_appended = false; | |
| 13100 |
1/2✓ Branch 0 taken 4343913 times.
✗ Branch 1 not taken.
|
4343913 | trx_t *trx = thd_to_trx(thd); |
| 13101 | |||
| 13102 | #ifdef WSREP_DEBUG_PRINT | ||
| 13103 | fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", table %s\nSQL: %s\n", | ||
| 13104 | wsrep_key_type_to_str(key_type), thd_get_thread_id(thd), trx->id, | ||
| 13105 | table_share->table_name.str, wsrep_thd_query(thd)); | ||
| 13106 | #endif /* WSREP_DEBUG_PRINT */ | ||
| 13107 | |||
| 13108 |
3/4✓ Branch 0 taken 4343913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 521167 times.
✓ Branch 3 taken 3822746 times.
|
4343913 | if (table_share && table_share->tmp_table != NO_TMP_TABLE) { |
| 13109 |
16/32✓ Branch 0 taken 13123 times.
✓ Branch 1 taken 508044 times.
✓ Branch 2 taken 13123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13123 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13123 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 13123 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13123 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 13123 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 13123 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 13123 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 13123 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 13123 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 13123 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 13123 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 13123 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 13123 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
|
521167 | WSREP_DEBUG( |
| 13110 | "Skip appending keys to write-set for" | ||
| 13111 | " temporary-tables DML (THD: %u tmp: %d SQL: %s)", | ||
| 13112 | wsrep_thd_thread_id(thd), table_share->tmp_table, | ||
| 13113 | (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); | ||
| 13114 |
1/2✓ Branch 0 taken 521167 times.
✗ Branch 1 not taken.
|
521167 | DBUG_RETURN(0); |
| 13115 | } | ||
| 13116 | |||
| 13117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3822746 times.
|
3822746 | if (wsrep_protocol_version == 0) { |
| 13118 | uint len; | ||
| 13119 | ✗ | char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH + 1] = {'\0'}; | |
| 13120 | ✗ | char *key = &keyval[0]; | |
| 13121 | bool is_null; | ||
| 13122 | |||
| 13123 | ✗ | len = wsrep_store_key_val_for_row(thd, table, 0, key, | |
| 13124 | WSREP_MAX_SUPPORTED_KEY_LENGTH, record0, | ||
| 13125 | &is_null, m_prebuilt); | ||
| 13126 | |||
| 13127 | ✗ | if (!is_null) { | |
| 13128 | ✗ | rcode = wsrep_append_key(thd, trx, table_share, keyval, len, key_type); | |
| 13129 | ✗ | if (rcode) DBUG_RETURN(rcode); | |
| 13130 | } else { | ||
| 13131 | ✗ | WSREP_DEBUG("Skip appending NULL key (proto 0): %s", | |
| 13132 | wsrep_thd_query(thd)); | ||
| 13133 | } | ||
| 13134 | } else { | ||
| 13135 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3822746 times.
|
3822746 | ut_a(table->s->keys <= 256); |
| 13136 | uint i; | ||
| 13137 | 3822746 | bool hasPK = false; | |
| 13138 | |||
| 13139 |
2/2✓ Branch 0 taken 2189466 times.
✓ Branch 1 taken 1635422 times.
|
3824888 | for (i = 0; i < table->s->keys; ++i) { |
| 13140 | 2189466 | KEY *key_info = table->key_info + i; | |
| 13141 |
2/2✓ Branch 0 taken 2187324 times.
✓ Branch 1 taken 2142 times.
|
2189466 | if (key_info->flags & HA_NOSAME) { |
| 13142 | 2187324 | hasPK = true; | |
| 13143 | 2187324 | break; | |
| 13144 | } | ||
| 13145 | } | ||
| 13146 | |||
| 13147 |
2/2✓ Branch 0 taken 2205001 times.
✓ Branch 1 taken 3822745 times.
|
6027746 | for (i = 0; i < table->s->keys; ++i) { |
| 13148 | 2205001 | KEY *key_info = table->key_info + i; | |
| 13149 | |||
| 13150 |
1/2✓ Branch 0 taken 2205001 times.
✗ Branch 1 not taken.
|
2205001 | dict_index_t *idx = innobase_get_index(i); |
| 13151 |
1/2✓ Branch 0 taken 2205001 times.
✗ Branch 1 not taken.
|
2205001 | dict_table_t *tab = (idx) ? idx->table : NULL; |
| 13152 | |||
| 13153 | /* keyval[] shall contain an ordinal number at byte 0 | ||
| 13154 | and the actual key data shall be written at byte 1. | ||
| 13155 | Hence the total data length is the key length + 1 */ | ||
| 13156 | 2205001 | char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH + 1] = {'\0'}; | |
| 13157 | 2205001 | char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH + 1] = {'\0'}; | |
| 13158 | 2205001 | keyval0[0] = (char)i; | |
| 13159 | 2205001 | keyval1[0] = (char)i; | |
| 13160 | 2205001 | char *key0 = &keyval0[1]; | |
| 13161 | 2205001 | char *key1 = &keyval1[1]; | |
| 13162 | |||
| 13163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2205001 times.
|
2205001 | if (!tab) { |
| 13164 | ✗ | WSREP_WARN("MySQL-InnoDB key mismatch %s %s", table->s->table_name.str, | |
| 13165 | key_info->name); | ||
| 13166 | } | ||
| 13167 | |||
| 13168 | const bool referenced_by_fk = | ||
| 13169 |
1/2✓ Branch 0 taken 2205001 times.
✗ Branch 1 not taken.
|
2205001 | dict_table_is_referenced_by_foreign_key(m_prebuilt->table); |
| 13170 | |||
| 13171 | /* !hasPK == table with no PK, | ||
| 13172 | must append all non-unique keys */ | ||
| 13173 |
8/10✓ Branch 0 taken 2142 times.
✓ Branch 1 taken 2202859 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2142 times.
✓ Branch 4 taken 15122 times.
✓ Branch 5 taken 2187737 times.
✓ Branch 6 taken 15122 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2189886 times.
✓ Branch 9 taken 15115 times.
|
2220123 | if ((!hasPK && wsrep_certify_nonPK) || key_info->flags & HA_NOSAME || |
| 13174 |
4/6✓ Branch 0 taken 15122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15115 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 15115 times.
|
15122 | ((tab && wsrep_is_FK_index(tab, idx)) || |
| 13175 | ✗ | (!tab && referenced_by_fk))) { | |
| 13176 | bool is_null0; | ||
| 13177 |
1/2✓ Branch 0 taken 2189886 times.
✗ Branch 1 not taken.
|
2189886 | uint len0 = wsrep_store_key_val_for_row(thd, table, i, key0, |
| 13178 | WSREP_MAX_SUPPORTED_KEY_LENGTH, | ||
| 13179 | record0, &is_null0, m_prebuilt); | ||
| 13180 |
2/2✓ Branch 0 taken 606490 times.
✓ Branch 1 taken 1583396 times.
|
2189886 | if (record1) { |
| 13181 | bool is_null1; | ||
| 13182 |
1/2✓ Branch 0 taken 606490 times.
✗ Branch 1 not taken.
|
606490 | uint len1 = wsrep_store_key_val_for_row( |
| 13183 | thd, table, i, key1, WSREP_MAX_SUPPORTED_KEY_LENGTH, record1, | ||
| 13184 | &is_null1, m_prebuilt); | ||
| 13185 | |||
| 13186 |
3/4✓ Branch 0 taken 606490 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 606488 times.
✓ Branch 3 taken 2 times.
|
606490 | if (is_null0 != is_null1 || len0 != len1 || |
| 13187 |
2/2✓ Branch 0 taken 2241 times.
✓ Branch 1 taken 604247 times.
|
606488 | memcmp(key0, key1, len0)) { |
| 13188 | /* This key has chaged. If it | ||
| 13189 | is unique, this is an exclusive | ||
| 13190 | operation -> upgrade key type */ | ||
| 13191 |
2/2✓ Branch 0 taken 1240 times.
✓ Branch 1 taken 1003 times.
|
2243 | if (key_info->flags & HA_NOSAME) { |
| 13192 | 1240 | key_type = WSREP_SERVICE_KEY_EXCLUSIVE; | |
| 13193 | } | ||
| 13194 | |||
| 13195 |
1/2✓ Branch 0 taken 2243 times.
✗ Branch 1 not taken.
|
2243 | if (!is_null1) { |
| 13196 | 4486 | rcode = wsrep_append_key(thd, trx, table_share, keyval1, | |
| 13197 | /* for len1+1 see keyval1 | ||
| 13198 | initialization comment */ | ||
| 13199 |
1/2✓ Branch 0 taken 2243 times.
✗ Branch 1 not taken.
|
2243 | len1 + 1, key_type); |
| 13200 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2243 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2243 | if (rcode) DBUG_RETURN(rcode); |
| 13201 | } | ||
| 13202 | } | ||
| 13203 | } | ||
| 13204 | |||
| 13205 |
2/2✓ Branch 0 taken 2189883 times.
✓ Branch 1 taken 3 times.
|
2189886 | if (!is_null0) { |
| 13206 | 4379766 | rcode = wsrep_append_key(thd, trx, table_share, | |
| 13207 | /* for len0+1 see keyval0 | ||
| 13208 | initialization comment */ | ||
| 13209 |
1/2✓ Branch 0 taken 2189883 times.
✗ Branch 1 not taken.
|
2189883 | keyval0, len0 + 1, key_type); |
| 13210 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2189882 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2189883 | if (rcode) DBUG_RETURN(rcode); |
| 13211 | |||
| 13212 |
3/4✓ Branch 0 taken 2149 times.
✓ Branch 1 taken 2187733 times.
✓ Branch 2 taken 2149 times.
✗ Branch 3 not taken.
|
2189882 | if (key_info->flags & HA_NOSAME || |
| 13213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2149 times.
|
2149 | key_type == WSREP_SERVICE_KEY_SHARED || |
| 13214 | key_type == WSREP_SERVICE_KEY_REFERENCE) | ||
| 13215 | 2187733 | key_appended = true; | |
| 13216 | } else { | ||
| 13217 |
1/26✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
3 | WSREP_DEBUG("NULL key skipped: %s", wsrep_thd_query(thd)); |
| 13218 | } | ||
| 13219 | } | ||
| 13220 | } | ||
| 13221 | } | ||
| 13222 | |||
| 13223 | /* if no PK, calculate hash of full row, to be the key value */ | ||
| 13224 |
4/4✓ Branch 0 taken 1635425 times.
✓ Branch 1 taken 2187320 times.
✓ Branch 2 taken 1635424 times.
✓ Branch 3 taken 1 times.
|
3822745 | if (!key_appended && wsrep_certify_nonPK) { |
| 13225 | uchar digest[16]; | ||
| 13226 | int rcode; | ||
| 13227 | |||
| 13228 |
1/2✓ Branch 0 taken 1635424 times.
✗ Branch 1 not taken.
|
1635424 | wsrep_calc_row_hash(digest, record0, table, m_prebuilt, thd); |
| 13229 |
2/4✓ Branch 0 taken 1635424 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1635424 times.
|
1635424 | if ((rcode = wsrep_append_key(thd, trx, table_share, (const char *)digest, |
| 13230 | 16, key_type))) { | ||
| 13231 | ✗ | DBUG_RETURN(rcode); | |
| 13232 | } | ||
| 13233 | |||
| 13234 |
2/2✓ Branch 0 taken 4854 times.
✓ Branch 1 taken 1630570 times.
|
1635424 | if (record1) { |
| 13235 |
1/2✓ Branch 0 taken 4854 times.
✗ Branch 1 not taken.
|
4854 | wsrep_calc_row_hash(digest, record1, table, m_prebuilt, thd); |
| 13236 |
2/4✓ Branch 0 taken 4854 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4854 times.
|
4854 | if ((rcode = wsrep_append_key(thd, trx, table_share, (const char *)digest, |
| 13237 | 16, key_type))) { | ||
| 13238 | ✗ | DBUG_RETURN(rcode); | |
| 13239 | } | ||
| 13240 | } | ||
| 13241 |
1/2✓ Branch 0 taken 1635424 times.
✗ Branch 1 not taken.
|
1635424 | DBUG_RETURN(0); |
| 13242 | } | ||
| 13243 | |||
| 13244 | /* If certification of table with non-PK is blocked by setting | ||
| 13245 | relevant configuration option wsrep_certify_nonPK = OFF/0 then | ||
| 13246 | ensure that thd->wsrep_ws_handle->trx_id = WSREP_UNDEFINED_TRX_ID. | ||
| 13247 | If not then make sure you set it to WSREP_UNDEFINED_TRX_ID. | ||
| 13248 | But what may cause trx_id to set if append-key is blocked ? | ||
| 13249 | CREATE TABLE ... SELECT statement will cause a fake_trx_id to set | ||
| 13250 | while processing SELECT statement. */ | ||
| 13251 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2187320 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2187321 | if (!key_appended && !wsrep_certify_nonPK) { |
| 13252 |
10/22✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
1 | WSREP_WARN( |
| 13253 | "Table without explict primary key (not-recommended)" | ||
| 13254 | " and certification of nonPK table is OFF too"); | ||
| 13255 | // wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, WSREP_UNDEFINED_TRX_ID); | ||
| 13256 | } | ||
| 13257 | |||
| 13258 |
1/2✓ Branch 0 taken 2187321 times.
✗ Branch 1 not taken.
|
2187321 | DBUG_RETURN(0); |
| 13259 | } | ||
| 13260 | #endif /* WITH_WSREP */ | ||
| 13261 | |||
| 13262 | /** | ||
| 13263 | Store a reference to the current row to 'ref' field of the handle. | ||
| 13264 | Note that in the case where we have generated the clustered index for the | ||
| 13265 | table, the function parameter is illogical: we MUST ASSUME that 'record' | ||
| 13266 | is the current 'position' of the handle, because if row ref is actually | ||
| 13267 | the row id internally generated in InnoDB, then 'record' does not contain | ||
| 13268 | it. We just guess that the row id must be for the record where the handle | ||
| 13269 | was positioned the last time. | ||
| 13270 | @param[in] record row in MySQL format */ | ||
| 13271 | 9085150 | void ha_innobase::position(const uchar *record) { | |
| 13272 | uint len; | ||
| 13273 | |||
| 13274 |
1/2✓ Branch 0 taken 9085151 times.
✗ Branch 1 not taken.
|
9085150 | DBUG_TRACE; |
| 13275 |
3/6✓ Branch 0 taken 9085151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9085151 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9085151 times.
|
9085151 | assert(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 13276 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9085151 times.
|
9085151 | assert(table_share->is_missing_primary_key() == |
| 13277 | (bool)m_prebuilt->clust_index_was_generated); | ||
| 13278 | |||
| 13279 |
2/2✓ Branch 0 taken 8327159 times.
✓ Branch 1 taken 757992 times.
|
9085151 | if (m_prebuilt->clust_index_was_generated) { |
| 13280 | /* No primary key was defined for the table and we | ||
| 13281 | generated the clustered index from row id: the | ||
| 13282 | row reference will be the row id, not any key value | ||
| 13283 | that MySQL knows of */ | ||
| 13284 | |||
| 13285 | 8327159 | len = DATA_ROW_ID_LEN; | |
| 13286 | |||
| 13287 | 8327159 | memcpy(ref, m_prebuilt->row_id, len); | |
| 13288 | } else { | ||
| 13289 | /* Copy primary key as the row reference */ | ||
| 13290 | 757992 | KEY *key_info = table->key_info + table_share->primary_key; | |
| 13291 |
1/2✓ Branch 0 taken 757992 times.
✗ Branch 1 not taken.
|
757992 | key_copy(ref, (uchar *)record, key_info, key_info->key_length); |
| 13292 | 757992 | len = key_info->key_length; | |
| 13293 | } | ||
| 13294 | |||
| 13295 | /* We assume that the 'ref' value len is always fixed for the same | ||
| 13296 | table. */ | ||
| 13297 | |||
| 13298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9085151 times.
|
9085151 | if (len != ref_length) { |
| 13299 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_DIFF_IN_REF_LEN, (ulong)len, | |
| 13300 | (ulong)ref_length); | ||
| 13301 | } | ||
| 13302 | 9085151 | } | |
| 13303 | |||
| 13304 | /** Set up base columns for virtual column | ||
| 13305 | @param[in] table the InnoDB table | ||
| 13306 | @param[in] field MySQL field | ||
| 13307 | @param[in,out] v_col virtual column to be set up */ | ||
| 13308 | 28050 | void innodb_base_col_setup(dict_table_t *table, const Field *field, | |
| 13309 | dict_v_col_t *v_col) { | ||
| 13310 | 28050 | int n = 0; | |
| 13311 | |||
| 13312 |
2/2✓ Branch 0 taken 499606 times.
✓ Branch 1 taken 28050 times.
|
527656 | for (uint i = 0; i < field->table->s->fields; ++i) { |
| 13313 | 499606 | const Field *base_field = field->table->field[i]; | |
| 13314 | |||
| 13315 |
6/6✓ Branch 0 taken 123461 times.
✓ Branch 1 taken 376145 times.
✓ Branch 2 taken 27513 times.
✓ Branch 3 taken 95948 times.
✓ Branch 4 taken 27513 times.
✓ Branch 5 taken 472093 times.
|
623067 | if (!base_field->is_virtual_gcol() && |
| 13316 | 123461 | bitmap_is_set(&field->gcol_info->base_columns_map, i)) { | |
| 13317 | ulint z; | ||
| 13318 | |||
| 13319 |
1/2✓ Branch 0 taken 52467 times.
✗ Branch 1 not taken.
|
52467 | for (z = 0; z < table->n_cols; z++) { |
| 13320 | 52467 | const char *name = table->get_col_name(z); | |
| 13321 |
2/2✓ Branch 0 taken 27513 times.
✓ Branch 1 taken 24954 times.
|
52467 | if (!innobase_strcasecmp(name, base_field->field_name)) { |
| 13322 | 27513 | break; | |
| 13323 | } | ||
| 13324 | } | ||
| 13325 | |||
| 13326 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27513 times.
|
27513 | ut_ad(z != table->n_cols); |
| 13327 | |||
| 13328 | 27513 | v_col->base_col[n] = table->get_col(z); | |
| 13329 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27513 times.
|
27513 | ut_ad(v_col->base_col[n]->ind == z); |
| 13330 | 27513 | n++; | |
| 13331 | } | ||
| 13332 | } | ||
| 13333 | 28050 | } | |
| 13334 | |||
| 13335 | /** Set up base columns for stored column | ||
| 13336 | @param[in] table InnoDB table | ||
| 13337 | @param[in] field MySQL field | ||
| 13338 | @param[in,out] s_col stored column */ | ||
| 13339 | 1589 | void innodb_base_col_setup_for_stored(const dict_table_t *table, | |
| 13340 | const Field *field, dict_s_col_t *s_col) { | ||
| 13341 | 1589 | ulint n = 0; | |
| 13342 | |||
| 13343 |
2/2✓ Branch 0 taken 2472 times.
✓ Branch 1 taken 41 times.
|
2513 | for (uint i = 0; i < field->table->s->fields; ++i) { |
| 13344 | 2472 | const Field *base_field = field->table->field[i]; | |
| 13345 | |||
| 13346 |
8/8✓ Branch 0 taken 240 times.
✓ Branch 1 taken 2232 times.
✓ Branch 2 taken 127 times.
✓ Branch 3 taken 113 times.
✓ Branch 4 taken 1592 times.
✓ Branch 5 taken 767 times.
✓ Branch 6 taken 1592 times.
✓ Branch 7 taken 880 times.
|
4831 | if (!innobase_is_v_fld(base_field) && |
| 13347 | 2359 | bitmap_is_set(&field->gcol_info->base_columns_map, i)) { | |
| 13348 | ulint z; | ||
| 13349 |
1/2✓ Branch 0 taken 2385 times.
✗ Branch 1 not taken.
|
2385 | for (z = 0; z < table->n_cols; z++) { |
| 13350 | 2385 | const char *name = table->get_col_name(z); | |
| 13351 |
2/2✓ Branch 0 taken 1592 times.
✓ Branch 1 taken 793 times.
|
2385 | if (!innobase_strcasecmp(name, base_field->field_name)) { |
| 13352 | 1592 | break; | |
| 13353 | } | ||
| 13354 | } | ||
| 13355 | |||
| 13356 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1592 times.
|
1592 | ut_ad(z != table->n_cols); |
| 13357 | |||
| 13358 | 1592 | s_col->base_col[n] = table->get_col(z); | |
| 13359 | 1592 | n++; | |
| 13360 | |||
| 13361 |
2/2✓ Branch 0 taken 1548 times.
✓ Branch 1 taken 44 times.
|
1592 | if (n == s_col->num_base) { |
| 13362 | 1548 | break; | |
| 13363 | } | ||
| 13364 | } | ||
| 13365 | } | ||
| 13366 | 1589 | } | |
| 13367 | |||
| 13368 | /** If encryption is requested, check for master key availability | ||
| 13369 | and set the encryption flag in table flags | ||
| 13370 | @param[in,out] table table object | ||
| 13371 | @return on success DB_SUCCESS else DB_UNSPPORTED on failure */ | ||
| 13372 | 1931 | dberr_t create_table_info_t::enable_master_key_encryption(dict_table_t *table) { | |
| 13373 | 1931 | const char *encrypt = m_create_info->encrypt_type.str; | |
| 13374 | |||
| 13375 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1931 times.
|
1931 | if (Encryption::is_none(encrypt)) return (DB_SUCCESS); |
| 13376 | |||
| 13377 | /* If table is part of tablespace - no need for retrieving | ||
| 13378 | master key as tablespace key was already decrypted | ||
| 13379 | either by validate_first_page or during tablespace creation. | ||
| 13380 | Just set the encryption flag and return. */ | ||
| 13381 |
2/2✓ Branch 0 taken 859 times.
✓ Branch 1 taken 1072 times.
|
1931 | if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE)) { |
| 13382 | 859 | DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE); | |
| 13383 | 859 | return (DB_SUCCESS); | |
| 13384 | } | ||
| 13385 | |||
| 13386 | /* Set the encryption flag. */ | ||
| 13387 | 1072 | byte *master_key = nullptr; | |
| 13388 | uint32_t master_key_id; | ||
| 13389 | |||
| 13390 | /* Check if keyring is ready. */ | ||
| 13391 | 1072 | Encryption::get_master_key(&master_key_id, &master_key); | |
| 13392 | |||
| 13393 | 1072 | dberr_t err = DB_SUCCESS; | |
| 13394 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1049 times.
|
1072 | if (master_key == nullptr) { |
| 13395 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 13396 | 23 | err = DB_UNSUPPORTED; | |
| 13397 | } else { | ||
| 13398 |
1/2✓ Branch 0 taken 1049 times.
✗ Branch 1 not taken.
|
1049 | my_free(master_key); |
| 13399 | 1049 | DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE); | |
| 13400 | } | ||
| 13401 | |||
| 13402 | 1072 | return (err); | |
| 13403 | } | ||
| 13404 | |||
| 13405 | /** Retrive keyring encryption mode | ||
| 13406 | @param[in] encrypt_type from ENCRYPTION clause | ||
| 13407 | @param[in] explicit_encryption was ENCRYPTION clause used | ||
| 13408 | @param[in] flags tabelspace flags | ||
| 13409 | @retval FIL_ENCRYPTION_OFF tablespace should be skipped by | ||
| 13410 | encryption threads | ||
| 13411 | FIL_ENCRYPTION_DEFAULT online encryption allowed by | ||
| 13412 | encryption threads | ||
| 13413 | FIL_ENCRYPTION_ON table should be keyring encrypted */ | ||
| 13414 | 335405 | static fil_encryption_t get_encryption_mode(const char *encrypt_type, | |
| 13415 | bool explicit_encryption) { | ||
| 13416 |
6/6✓ Branch 0 taken 509 times.
✓ Branch 1 taken 334896 times.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 268 times.
✓ Branch 4 taken 241 times.
✓ Branch 5 taken 335164 times.
|
335405 | if (explicit_encryption && innobase_strcasecmp(encrypt_type, "n") == 0) { |
| 13417 | 241 | return FIL_ENCRYPTION_OFF; | |
| 13418 | } | ||
| 13419 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 335165 times.
|
335164 | if (Encryption::is_keyring(encrypt_type)) { |
| 13420 | ✗ | return FIL_ENCRYPTION_ON; | |
| 13421 | } | ||
| 13422 | 335165 | return FIL_ENCRYPTION_DEFAULT; | |
| 13423 | } | ||
| 13424 | |||
| 13425 | 5 | dberr_t create_table_info_t::check_tablespace_key( | |
| 13426 | const EncryptionKeyId encryption_key_id) { | ||
| 13427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (!Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist( |
| 13428 | encryption_key_id, server_uuid)) { | ||
| 13429 | ✗ | my_printf_error( | |
| 13430 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 13431 | "Seems that keyring is down. It is not possible to create encrypted " | ||
| 13432 | "tables " | ||
| 13433 | " without keyring. Please install a keyring and try again.", | ||
| 13434 | MYF(0)); | ||
| 13435 | ✗ | return (DB_UNSUPPORTED); | |
| 13436 | } | ||
| 13437 | 5 | return DB_SUCCESS; | |
| 13438 | } | ||
| 13439 | |||
| 13440 | /** Enable keyring encryption for table | ||
| 13441 | @param[in,out] table table to have its encryption flag set | ||
| 13442 | in case it should be KEYRING encrypted | ||
| 13443 | @param[out] keyring_encryption_mode FIL_ENCRYPTION_ON | | ||
| 13444 | FIL_ENCRYPTION_OFF | FIL_ENCRYPTION_DEFAULT | ||
| 13445 | @retval DB_UNSUPPORTED on error | ||
| 13446 | DB_SUCCESS on success */ | ||
| 13447 | 334520 | dberr_t create_table_info_t::enable_keyring_encryption( | |
| 13448 | dict_table_t *table, fil_encryption_t &keyring_encryption_mode) { | ||
| 13449 | 334521 | keyring_encryption_mode = | |
| 13450 | 669041 | get_encryption_mode(m_create_info->encrypt_type.str, | |
| 13451 | 334520 | m_create_info->used_fields & HA_CREATE_USED_ENCRYPT); | |
| 13452 | |||
| 13453 |
1/2✓ Branch 0 taken 334522 times.
✗ Branch 1 not taken.
|
669043 | bool is_encrypted = keyring_encryption_mode == FIL_ENCRYPTION_ON || |
| 13454 |
3/4✓ Branch 0 taken 334522 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 334516 times.
|
669044 | (keyring_encryption_mode == FIL_ENCRYPTION_DEFAULT && |
| 13455 | 334522 | Encryption::is_online_encryption_on()); | |
| 13456 | |||
| 13457 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 334516 times.
|
334521 | if (is_encrypted) |
| 13458 | 5 | DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE); | |
| 13459 | |||
| 13460 |
3/4✓ Branch 0 taken 334515 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 334515 times.
|
334521 | if (is_encrypted || m_create_info->was_encryption_key_id_set) |
| 13461 | 6 | return check_tablespace_key(m_create_info->encryption_key_id); | |
| 13462 | |||
| 13463 | 334515 | return DB_SUCCESS; | |
| 13464 | } | ||
| 13465 | |||
| 13466 | /** Create a table definition to an InnoDB database. | ||
| 13467 | @param[in] dd_table dd::Table or nullptr for intrinsic table | ||
| 13468 | @param[in] old_part_table dd::Table from an old partition for partitioned | ||
| 13469 | table, NULL otherwise. | ||
| 13470 | @return HA_* level error */ | ||
| 13471 | 348223 | [[nodiscard]] inline int create_table_info_t::create_table_def( | |
| 13472 | const dd::Table *dd_table, const dd::Table *old_part_table) { | ||
| 13473 | dict_table_t *table; | ||
| 13474 | ulint n_cols; | ||
| 13475 | 348223 | dberr_t err = DB_SUCCESS; | |
| 13476 | ulint col_type; | ||
| 13477 | ulint col_len; | ||
| 13478 | ulint compressed; | ||
| 13479 | ulint i; | ||
| 13480 | 348223 | ulint j = 0; | |
| 13481 | 348223 | ulint doc_id_col = 0; | |
| 13482 | 348223 | bool has_doc_id_col = false; | |
| 13483 | mem_heap_t *heap; | ||
| 13484 | 348223 | ulint num_v = 0; | |
| 13485 | 348223 | ulint num_m_v = 0; | |
| 13486 | 348223 | space_id_t space_id = 0; | |
| 13487 | 348223 | dd::Object_id dd_space_id = dd::INVALID_OBJECT_ID; | |
| 13488 | ulint actual_n_cols; | ||
| 13489 | |||
| 13490 | fil_encryption_t keyring_encryption_option = | ||
| 13491 | 348223 | Encryption::none_explicitly_specified(m_create_info->explicit_encryption, | |
| 13492 | 348223 | m_create_info->encrypt_type.str) | |
| 13493 |
2/2✓ Branch 0 taken 11742 times.
✓ Branch 1 taken 336481 times.
|
348223 | ? FIL_ENCRYPTION_OFF |
| 13494 | 348223 | : FIL_ENCRYPTION_DEFAULT; | |
| 13495 | |||
| 13496 | 348223 | uint32_t i_c = 0; | |
| 13497 | 348223 | uint32_t c_c = 0; | |
| 13498 | 348223 | uint32_t t_c = 0; | |
| 13499 | 348223 | uint32_t c_r_v = 0; | |
| 13500 | |||
| 13501 |
1/2✓ Branch 0 taken 348225 times.
✗ Branch 1 not taken.
|
348223 | DBUG_TRACE; |
| 13502 |
5/8✓ Branch 0 taken 348225 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 348224 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 348214 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
|
348225 | DBUG_PRINT("enter", ("table_name: %s", m_table_name)); |
| 13503 | |||
| 13504 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 348224 times.
|
348224 | assert(m_trx->mysql_thd == m_thd); |
| 13505 | |||
| 13506 | bool part_table_with_instant_cols = | ||
| 13507 |
5/6✓ Branch 0 taken 133 times.
✓ Branch 1 taken 348091 times.
✓ Branch 2 taken 133 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121 times.
✓ Branch 5 taken 12 times.
|
348224 | (old_part_table != nullptr && dd_table_has_row_versions(*old_part_table)); |
| 13508 | |||
| 13509 | /* MySQL does the name length check. But we do additional check | ||
| 13510 | on the name length here */ | ||
| 13511 | 348224 | const size_t table_name_len = strlen(m_table_name); | |
| 13512 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 348224 times.
|
348224 | if (table_name_len > MAX_FULL_NAME_LEN) { |
| 13513 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME, | |
| 13514 | "InnoDB: Table Name or Database Name is too long"); | ||
| 13515 | |||
| 13516 | ✗ | return HA_ERR_WRONG_TABLE_NAME; | |
| 13517 | } | ||
| 13518 | |||
| 13519 | /* Make sure that the table name is acceptable. */ | ||
| 13520 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 348224 times.
|
348224 | if (m_table_name[table_name_len - 1] == '/') { |
| 13521 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME, | |
| 13522 | "InnoDB: Table name is empty"); | ||
| 13523 | |||
| 13524 | ✗ | return HA_ERR_WRONG_TABLE_NAME; | |
| 13525 | } | ||
| 13526 | |||
| 13527 | fts_aux_table_t aux_table; | ||
| 13528 |
3/4✓ Branch 0 taken 348222 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 348196 times.
|
348224 | if (fts_is_aux_table_name(&aux_table, m_table_name, strlen(m_table_name))) { |
| 13529 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | push_warning_printf( |
| 13530 | m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME, | ||
| 13531 | "Invalid table name. `%s` has the form of an FTS auxiliary table name", | ||
| 13532 | m_table_name); | ||
| 13533 | 26 | return HA_ERR_WRONG_TABLE_NAME; | |
| 13534 | } | ||
| 13535 | |||
| 13536 | 348196 | n_cols = m_form->s->fields; | |
| 13537 | |||
| 13538 | /* Find out any virtual column */ | ||
| 13539 |
2/2✓ Branch 0 taken 2485532 times.
✓ Branch 1 taken 348199 times.
|
2833731 | for (i = 0; i < n_cols; i++) { |
| 13540 | 2485532 | Field *field = m_form->field[i]; | |
| 13541 | |||
| 13542 |
7/10✓ Branch 0 taken 7992 times.
✓ Branch 1 taken 2477540 times.
✓ Branch 2 taken 1577 times.
✓ Branch 3 taken 6415 times.
✓ Branch 4 taken 2479119 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2479119 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2485535 times.
|
2485532 | ut_ad(!(!innobase_is_v_fld(field) && innobase_is_multi_value_fld(field))); |
| 13543 | |||
| 13544 |
4/4✓ Branch 0 taken 7992 times.
✓ Branch 1 taken 2477543 times.
✓ Branch 2 taken 6415 times.
✓ Branch 3 taken 1577 times.
|
2485535 | if (innobase_is_v_fld(field)) { |
| 13545 | 6415 | num_v++; | |
| 13546 | |||
| 13547 |
3/4✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 243 times.
✓ Branch 3 taken 6172 times.
|
6415 | if (innobase_is_multi_value_fld(field)) { |
| 13548 | 243 | num_m_v++; | |
| 13549 | } | ||
| 13550 | } | ||
| 13551 | } | ||
| 13552 | |||
| 13553 | /* Check whether there already exists a FTS_DOC_ID column */ | ||
| 13554 |
3/4✓ Branch 0 taken 348197 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 348159 times.
|
348199 | if (create_table_check_doc_id_col(m_trx->mysql_thd, m_form, &doc_id_col)) { |
| 13555 | /* Raise error if the Doc ID column is of wrong type or name */ | ||
| 13556 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 37 times.
|
38 | if (doc_id_col == ULINT_UNDEFINED) { |
| 13557 | 1 | err = DB_ERROR; | |
| 13558 | 1 | goto error_ret; | |
| 13559 | } else { | ||
| 13560 | 37 | has_doc_id_col = true; | |
| 13561 | } | ||
| 13562 | } | ||
| 13563 | |||
| 13564 | /* For single-table tablespaces, we pass 0 as the space id, and then | ||
| 13565 | determine the actual space id when the tablespace is created. */ | ||
| 13566 |
2/2✓ Branch 0 taken 24392 times.
✓ Branch 1 taken 323804 times.
|
348196 | if (DICT_TF_HAS_SHARED_SPACE(m_flags)) { |
| 13567 |
3/6✓ Branch 0 taken 24392 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24392 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 24392 times.
|
24392 | ut_ad(m_tablespace != nullptr && m_tablespace[0] != '\0'); |
| 13568 | |||
| 13569 |
1/2✓ Branch 0 taken 24392 times.
✗ Branch 1 not taken.
|
24392 | space_id = fil_space_get_id_by_name(m_tablespace); |
| 13570 |
2/4✓ Branch 0 taken 24392 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24392 times.
✗ Branch 3 not taken.
|
24392 | dd_space_id = (dd_table != nullptr ? dd_table->tablespace_id() |
| 13571 | : dd::INVALID_OBJECT_ID); | ||
| 13572 | } | ||
| 13573 | |||
| 13574 | /* Adjust the number of columns for the FTS hidden field */ | ||
| 13575 | 348196 | actual_n_cols = n_cols; | |
| 13576 |
4/4✓ Branch 0 taken 470 times.
✓ Branch 1 taken 347726 times.
✓ Branch 2 taken 451 times.
✓ Branch 3 taken 19 times.
|
348196 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID) && !has_doc_id_col) { |
| 13577 | 451 | actual_n_cols += 1; | |
| 13578 | } | ||
| 13579 | |||
| 13580 |
2/2✓ Branch 0 taken 121 times.
✓ Branch 1 taken 348075 times.
|
348196 | if (part_table_with_instant_cols) { |
| 13581 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | dd_table_get_column_counters(*old_part_table, i_c, c_c, t_c, c_r_v); |
| 13582 | } | ||
| 13583 | |||
| 13584 |
1/2✓ Branch 0 taken 348198 times.
✗ Branch 1 not taken.
|
348196 | table = dict_mem_table_create(m_table_name, space_id, actual_n_cols, num_v, |
| 13585 | num_m_v, m_flags, m_flags2, t_c - c_c); | ||
| 13586 | |||
| 13587 | /* Set dd tablespace id */ | ||
| 13588 | 348198 | table->dd_space_id = dd_space_id; | |
| 13589 | |||
| 13590 | /* Set the hidden doc_id column. */ | ||
| 13591 |
2/2✓ Branch 0 taken 470 times.
✓ Branch 1 taken 347728 times.
|
348198 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) { |
| 13592 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 451 times.
|
470 | table->fts->doc_col = has_doc_id_col ? doc_id_col : n_cols - num_v; |
| 13593 | } | ||
| 13594 | |||
| 13595 |
2/2✓ Branch 0 taken 429 times.
✓ Branch 1 taken 347769 times.
|
348198 | if (DICT_TF_HAS_DATA_DIR(m_flags)) { |
| 13596 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
|
429 | ut_a(strlen(m_remote_path) != 0); |
| 13597 | |||
| 13598 |
1/2✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
|
428 | table->data_dir_path = mem_heap_strdup(table->heap, m_remote_path); |
| 13599 | |||
| 13600 | } else { | ||
| 13601 | 347769 | table->data_dir_path = nullptr; | |
| 13602 | } | ||
| 13603 | |||
| 13604 |
2/2✓ Branch 0 taken 24392 times.
✓ Branch 1 taken 323806 times.
|
348197 | if (DICT_TF_HAS_SHARED_SPACE(m_flags)) { |
| 13605 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24392 times.
|
24392 | ut_ad(strlen(m_tablespace)); |
| 13606 |
1/2✓ Branch 0 taken 24392 times.
✗ Branch 1 not taken.
|
24392 | table->tablespace = mem_heap_strdup(table->heap, m_tablespace); |
| 13607 | } else { | ||
| 13608 | 323806 | table->tablespace = nullptr; | |
| 13609 | } | ||
| 13610 | |||
| 13611 | /* Initialize row version and column counts for new table */ | ||
| 13612 |
2/2✓ Branch 0 taken 348077 times.
✓ Branch 1 taken 121 times.
|
348198 | if (!part_table_with_instant_cols) { |
| 13613 | 348077 | table->current_row_version = 0; | |
| 13614 | 348077 | table->initial_col_count = n_cols - num_v; | |
| 13615 | 348077 | table->current_col_count = table->initial_col_count; | |
| 13616 | 348077 | table->total_col_count = table->initial_col_count; | |
| 13617 | } else { | ||
| 13618 | /* This is a new partition getting created. We need to inherit INSTANT | ||
| 13619 | instant metadata from old partition table */ | ||
| 13620 | 121 | table->initial_col_count = i_c; | |
| 13621 | 121 | table->current_col_count = c_c; | |
| 13622 | 121 | table->total_col_count = t_c; | |
| 13623 | 121 | table->current_row_version = c_r_v; | |
| 13624 | 121 | table->discard_after_ddl = true; | |
| 13625 | |||
| 13626 | #ifdef UNIV_DEBUG | ||
| 13627 | /* Get and set current row version for table */ | ||
| 13628 | 121 | uint32_t v = 0; | |
| 13629 |
6/10✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 791 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 791 times.
✓ Branch 9 taken 121 times.
|
912 | for (auto col : old_part_table->columns()) { |
| 13630 |
3/4✓ Branch 0 taken 791 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 721 times.
|
791 | if (dd_column_is_dropped(col)) { |
| 13631 |
1/2✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
|
70 | uint32_t value = dd_column_get_version_dropped(col); |
| 13632 | 70 | v = std::max(v, value); | |
| 13633 | 70 | continue; | |
| 13634 | 70 | } | |
| 13635 | |||
| 13636 |
3/4✓ Branch 0 taken 721 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✓ Branch 3 taken 552 times.
|
721 | if (dd_column_is_added(col)) { |
| 13637 |
1/2✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
|
169 | uint32_t value = dd_column_get_version_added(col); |
| 13638 | 169 | v = std::max(v, value); | |
| 13639 | 169 | continue; | |
| 13640 | 169 | } | |
| 13641 | } | ||
| 13642 |
2/4✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 121 times.
|
121 | ut_ad(dd_is_valid_row_version(v)); |
| 13643 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
|
121 | ut_ad(table->current_row_version == v); |
| 13644 | #endif | ||
| 13645 | } | ||
| 13646 | |||
| 13647 |
1/2✓ Branch 0 taken 348198 times.
✗ Branch 1 not taken.
|
348198 | heap = mem_heap_create(1000, UT_LOCATION_HERE); |
| 13648 | |||
| 13649 |
2/2✓ Branch 0 taken 2485526 times.
✓ Branch 1 taken 348195 times.
|
2833721 | for (i = 0; i < n_cols; i++) { |
| 13650 | ulint nulls_allowed; | ||
| 13651 | ulint unsigned_type; | ||
| 13652 | ulint binary_type; | ||
| 13653 | ulint long_true_varchar; | ||
| 13654 | ulint charset_no; | ||
| 13655 | ulint is_virtual; | ||
| 13656 | ulint is_multi_val; | ||
| 13657 | 2485526 | bool is_stored = false; | |
| 13658 | |||
| 13659 | 2485526 | Field *field = m_form->field[i]; | |
| 13660 | |||
| 13661 | /* Generate a unique column name by pre-pending table-name for | ||
| 13662 | intrinsic tables. For other tables (including normal | ||
| 13663 | temporary) column names are unique. If not, MySQL layer will | ||
| 13664 | block such statement. | ||
| 13665 | This is work-around fix till Optimizer can handle this issue | ||
| 13666 | (probably 5.7.4+). */ | ||
| 13667 | char field_name[MAX_FULL_NAME_LEN + 2 + 10]; | ||
| 13668 | |||
| 13669 |
6/8✓ Branch 0 taken 2485526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1705572 times.
✓ Branch 3 taken 779954 times.
✓ Branch 4 taken 1705572 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1705572 times.
✓ Branch 7 taken 779954 times.
|
2485526 | if (table->is_intrinsic() && field->table) { |
| 13670 | 1705572 | snprintf(field_name, sizeof(field_name), "%s_%s_" ULINTPF, | |
| 13671 | 1705572 | field->table->alias, field->field_name, i); | |
| 13672 | |||
| 13673 | } else { | ||
| 13674 | 779954 | snprintf(field_name, sizeof(field_name), "%s", field->field_name); | |
| 13675 | } | ||
| 13676 | |||
| 13677 |
1/2✓ Branch 0 taken 2485528 times.
✗ Branch 1 not taken.
|
2485526 | col_type = get_innobase_type_from_mysql_type(&unsigned_type, field); |
| 13678 | |||
| 13679 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2485528 times.
|
2485528 | if (!col_type) { |
| 13680 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 13681 | ER_CANT_CREATE_TABLE, | ||
| 13682 | "Error creating table '%s' with" | ||
| 13683 | " column '%s'. Please check its" | ||
| 13684 | " column type and try to re-create" | ||
| 13685 | " the table with an appropriate" | ||
| 13686 | " column type.", | ||
| 13687 | table->name.m_name, field->field_name); | ||
| 13688 | ✗ | goto err_col; | |
| 13689 | } | ||
| 13690 | |||
| 13691 |
2/2✓ Branch 0 taken 982852 times.
✓ Branch 1 taken 1502674 times.
|
2485528 | nulls_allowed = field->is_nullable() ? 0 : DATA_NOT_NULL; |
| 13692 |
3/4✓ Branch 0 taken 2485526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1316866 times.
✓ Branch 3 taken 1168660 times.
|
2485526 | binary_type = field->binary() ? DATA_BINARY_TYPE : 0; |
| 13693 | |||
| 13694 | 2485526 | charset_no = 0; | |
| 13695 | |||
| 13696 |
3/4✓ Branch 0 taken 2485528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1235870 times.
✓ Branch 3 taken 1249658 times.
|
2485526 | if (dtype_is_string_type(col_type)) { |
| 13697 |
1/2✓ Branch 0 taken 1235870 times.
✗ Branch 1 not taken.
|
1235870 | charset_no = (ulint)field->charset()->number; |
| 13698 | |||
| 13699 |
3/4✓ Branch 0 taken 1235870 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1235869 times.
|
1235870 | DBUG_EXECUTE_IF("simulate_max_char_col", |
| 13700 | charset_no = MAX_CHAR_COLL_NUM + 1;); | ||
| 13701 | |||
| 13702 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1235869 times.
|
1235870 | if (charset_no > MAX_CHAR_COLL_NUM) { |
| 13703 | /* in data0type.h we assume that the | ||
| 13704 | number fits in one byte in prtype */ | ||
| 13705 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, |
| 13706 | ER_CANT_CREATE_TABLE, | ||
| 13707 | "In InnoDB, charset-collation codes" | ||
| 13708 | " must be below 256." | ||
| 13709 | " Unsupported code %lu.", | ||
| 13710 | (ulong)charset_no); | ||
| 13711 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | mem_heap_free(heap); |
| 13712 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | dict_mem_table_free(table); |
| 13713 | |||
| 13714 | 1 | return ER_CANT_CREATE_TABLE; | |
| 13715 | } | ||
| 13716 | } | ||
| 13717 | |||
| 13718 |
1/2✓ Branch 0 taken 2485525 times.
✗ Branch 1 not taken.
|
2485527 | col_len = field->pack_length(); |
| 13719 | |||
| 13720 | /* The MySQL pack length contains 1 or 2 bytes length field | ||
| 13721 | for a true VARCHAR. Let us subtract that, so that the InnoDB | ||
| 13722 | column length in the InnoDB data dictionary is the real | ||
| 13723 | maximum byte length of the actual data. */ | ||
| 13724 | |||
| 13725 | 2485525 | long_true_varchar = 0; | |
| 13726 | |||
| 13727 |
3/4✓ Branch 0 taken 2485526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 930253 times.
✓ Branch 3 taken 1555273 times.
|
2485525 | if (field->type() == MYSQL_TYPE_VARCHAR) { |
| 13728 |
1/2✓ Branch 0 taken 930253 times.
✗ Branch 1 not taken.
|
930253 | col_len -= field->get_length_bytes(); |
| 13729 | |||
| 13730 |
3/4✓ Branch 0 taken 930253 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 249743 times.
✓ Branch 3 taken 680510 times.
|
930253 | if (field->get_length_bytes() == 2) { |
| 13731 | 249743 | long_true_varchar = DATA_LONG_TRUE_VARCHAR; | |
| 13732 | } | ||
| 13733 | } | ||
| 13734 | |||
| 13735 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2485526 times.
|
2485526 | if (col_type == DATA_POINT) { |
| 13736 | ✗ | col_len = DATA_POINT_LEN; | |
| 13737 | } | ||
| 13738 | |||
| 13739 |
4/4✓ Branch 0 taken 7992 times.
✓ Branch 1 taken 2477534 times.
✓ Branch 2 taken 6415 times.
✓ Branch 3 taken 1577 times.
|
2485526 | is_virtual = (innobase_is_v_fld(field)) ? DATA_VIRTUAL : 0; |
| 13740 | 2485526 | is_stored = innobase_is_s_fld(field); | |
| 13741 | /* Check if the the field has COMPRESSED attribute */ | ||
| 13742 | 2485525 | compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED) | |
| 13743 |
2/2✓ Branch 0 taken 2444 times.
✓ Branch 1 taken 2483081 times.
|
2485525 | ? DATA_COMPRESSED |
| 13744 | : 0; | ||
| 13745 | |||
| 13746 |
3/4✓ Branch 0 taken 2485525 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 243 times.
✓ Branch 3 taken 2485282 times.
|
2485525 | is_multi_val = innobase_is_multi_value_fld(field) ? DATA_MULTI_VALUE : 0; |
| 13747 | |||
| 13748 | /* First check whether the column to be added has a | ||
| 13749 | system reserved name. */ | ||
| 13750 |
3/4✓ Branch 0 taken 2485527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2485525 times.
|
2485525 | if (dict_col_name_is_reserved(field_name)) { |
| 13751 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_WRONG_COLUMN_NAME, MYF(0), field_name); |
| 13752 | 2 | err_col: | |
| 13753 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | dict_mem_table_free(table); |
| 13754 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | mem_heap_free(heap); |
| 13755 | |||
| 13756 | 2 | err = DB_ERROR; | |
| 13757 | 2 | goto error_ret; | |
| 13758 | } | ||
| 13759 | |||
| 13760 |
2/2✓ Branch 0 taken 2479108 times.
✓ Branch 1 taken 6417 times.
|
2485525 | if (!is_virtual) { |
| 13761 | 2479108 | uint32_t v_added = UINT32_UNDEFINED; | |
| 13762 | 2479108 | uint32_t v_dropped = UINT32_UNDEFINED; | |
| 13763 | 2479108 | uint32_t phy_pos = UINT32_UNDEFINED; | |
| 13764 | |||
| 13765 |
2/2✓ Branch 0 taken 459 times.
✓ Branch 1 taken 2478649 times.
|
2479108 | if (part_table_with_instant_cols) { |
| 13766 | const dd::Column *old_part_col = | ||
| 13767 |
1/2✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
|
459 | dd_find_column(old_part_table, field_name); |
| 13768 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 459 times.
|
459 | ut_ad(old_part_col != nullptr); |
| 13769 | |||
| 13770 | /* Get version added */ | ||
| 13771 |
1/2✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
|
459 | v_added = dd_column_get_version_added(old_part_col); |
| 13772 | |||
| 13773 | /* This columns must be present */ | ||
| 13774 |
2/4✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 459 times.
|
459 | ut_ad(!dd_column_is_dropped(old_part_col)); |
| 13775 | |||
| 13776 | /* Get physical pos */ | ||
| 13777 | 459 | const char *s = dd_column_key_strings[DD_INSTANT_PHYSICAL_POS]; | |
| 13778 |
4/8✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 459 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 459 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 459 times.
|
459 | ut_ad(old_part_col->se_private_data().exists(s)); |
| 13779 |
3/6✓ Branch 0 taken 459 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 459 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 459 times.
✗ Branch 5 not taken.
|
459 | old_part_col->se_private_data().get(s, &phy_pos); |
| 13780 | } | ||
| 13781 | |||
| 13782 |
1/2✓ Branch 0 taken 2479109 times.
✗ Branch 1 not taken.
|
2479109 | dict_mem_table_add_col( |
| 13783 | table, heap, field_name, col_type, | ||
| 13784 | 4958218 | dtype_form_prtype((ulint)field->type() | nulls_allowed | | |
| 13785 |
1/2✓ Branch 0 taken 2479109 times.
✗ Branch 1 not taken.
|
2479110 | unsigned_type | binary_type | |
| 13786 | long_true_varchar | compressed, | ||
| 13787 | charset_no), | ||
| 13788 |
2/4✓ Branch 0 taken 2479108 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2479110 times.
✗ Branch 3 not taken.
|
2479108 | col_len, !field->is_hidden_by_system(), phy_pos, v_added, v_dropped); |
| 13789 | |||
| 13790 |
3/4✓ Branch 0 taken 2479108 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✓ Branch 3 taken 2478939 times.
|
2479109 | if (dd_is_valid_row_version(v_added)) { |
| 13791 |
1/2✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
|
169 | mem_heap_t *instant_heap = mem_heap_create(1000, UT_LOCATION_HERE); |
| 13792 | const dd::Column *old_part_col = | ||
| 13793 |
1/2✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
|
169 | dd_find_column(old_part_table, field_name); |
| 13794 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 169 times.
|
169 | ut_ad(old_part_col != nullptr); |
| 13795 |
1/2✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
|
169 | dict_col_t *col = table->get_col(table->n_def - 1); |
| 13796 |
2/4✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✗ Branch 3 not taken.
|
169 | dd_parse_default_value(old_part_col->se_private_data(), col, heap); |
| 13797 |
1/2✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
|
169 | mem_heap_free(instant_heap); |
| 13798 | } | ||
| 13799 | } else { | ||
| 13800 |
2/2✓ Branch 0 taken 243 times.
✓ Branch 1 taken 6174 times.
|
6417 | if (is_multi_val) { |
| 13801 |
1/2✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
|
243 | col_len = field->key_length(); |
| 13802 | } | ||
| 13803 |
1/2✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
|
6415 | dict_mem_table_add_v_col( |
| 13804 | table, heap, field_name, col_type, | ||
| 13805 |
1/2✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
|
6415 | dtype_form_prtype((ulint)field->type() | nulls_allowed | |
| 13806 | 6415 | unsigned_type | binary_type | | |
| 13807 |
1/2✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
|
6415 | long_true_varchar | is_virtual | is_multi_val | |
| 13808 | compressed, | ||
| 13809 | charset_no), | ||
| 13810 | 6415 | col_len, i, field->gcol_info->non_virtual_base_columns(), | |
| 13811 |
1/2✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
|
6417 | !field->is_hidden_by_system()); |
| 13812 | } | ||
| 13813 | |||
| 13814 |
2/2✓ Branch 0 taken 1577 times.
✓ Branch 1 taken 2483946 times.
|
2485523 | if (is_stored) { |
| 13815 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1577 times.
|
1577 | ut_ad(!is_virtual); |
| 13816 | /* Added stored column in m_s_cols list. */ | ||
| 13817 |
1/2✓ Branch 0 taken 1577 times.
✗ Branch 1 not taken.
|
1577 | dict_mem_table_add_s_col(table, |
| 13818 | 1577 | field->gcol_info->non_virtual_base_columns()); | |
| 13819 | } | ||
| 13820 | } | ||
| 13821 | |||
| 13822 |
2/2✓ Branch 0 taken 2849 times.
✓ Branch 1 taken 345346 times.
|
348195 | if (num_v) { |
| 13823 |
2/2✓ Branch 0 taken 14511 times.
✓ Branch 1 taken 2849 times.
|
17360 | for (i = 0; i < n_cols; i++) { |
| 13824 | dict_v_col_t *v_col; | ||
| 13825 | |||
| 13826 | 14511 | Field *field = m_form->field[i]; | |
| 13827 | |||
| 13828 |
4/4✓ Branch 0 taken 7704 times.
✓ Branch 1 taken 6807 times.
✓ Branch 2 taken 1289 times.
✓ Branch 3 taken 6415 times.
|
14511 | if (!innobase_is_v_fld(field)) { |
| 13829 | 8096 | continue; | |
| 13830 | } | ||
| 13831 | |||
| 13832 |
1/2✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
|
6415 | v_col = dict_table_get_nth_v_col(table, j); |
| 13833 | |||
| 13834 | 6415 | j++; | |
| 13835 | |||
| 13836 |
1/2✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
|
6415 | innodb_base_col_setup(table, field, v_col); |
| 13837 | } | ||
| 13838 | } | ||
| 13839 | |||
| 13840 | /** Fill base columns for the stored column present in the list. */ | ||
| 13841 |
5/6✓ Branch 0 taken 1475 times.
✓ Branch 1 taken 346720 times.
✓ Branch 2 taken 1475 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1475 times.
✓ Branch 5 taken 346720 times.
|
348195 | if (table->s_cols && table->s_cols->size()) { |
| 13842 |
2/2✓ Branch 0 taken 8534 times.
✓ Branch 1 taken 1475 times.
|
10009 | for (i = 0; i < n_cols; i++) { |
| 13843 | 8534 | Field *field = m_form->field[i]; | |
| 13844 | |||
| 13845 |
2/2✓ Branch 0 taken 6957 times.
✓ Branch 1 taken 1577 times.
|
8534 | if (!innobase_is_s_fld(field)) { |
| 13846 | 6957 | continue; | |
| 13847 | } | ||
| 13848 | |||
| 13849 | 1577 | dict_s_col_list::iterator it; | |
| 13850 |
1/2✓ Branch 0 taken 1752 times.
✗ Branch 1 not taken.
|
1752 | for (it = table->s_cols->begin(); it != table->s_cols->end(); ++it) { |
| 13851 | 1752 | dict_s_col_t s_col = *it; | |
| 13852 | |||
| 13853 |
2/2✓ Branch 0 taken 1577 times.
✓ Branch 1 taken 175 times.
|
1752 | if (s_col.s_pos == i) { |
| 13854 |
1/2✓ Branch 0 taken 1577 times.
✗ Branch 1 not taken.
|
1577 | innodb_base_col_setup_for_stored(table, field, &s_col); |
| 13855 | 1577 | break; | |
| 13856 | } | ||
| 13857 | } | ||
| 13858 | } | ||
| 13859 | } | ||
| 13860 | |||
| 13861 | /* Add the FTS doc_id hidden column. */ | ||
| 13862 |
4/4✓ Branch 0 taken 470 times.
✓ Branch 1 taken 347725 times.
✓ Branch 2 taken 451 times.
✓ Branch 3 taken 19 times.
|
348195 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID) && !has_doc_id_col) { |
| 13863 |
1/2✓ Branch 0 taken 449 times.
✗ Branch 1 not taken.
|
451 | fts_add_doc_id_column(table, heap); |
| 13864 | } | ||
| 13865 | |||
| 13866 |
2/2✓ Branch 0 taken 336451 times.
✓ Branch 1 taken 11742 times.
|
348193 | if (keyring_encryption_option != FIL_ENCRYPTION_OFF) { |
| 13867 | 336451 | err = | |
| 13868 | 336451 | (Encryption::is_master_key_encryption(m_create_info->encrypt_type.str)) | |
| 13869 |
3/4✓ Branch 0 taken 1931 times.
✓ Branch 1 taken 334521 times.
✓ Branch 2 taken 1931 times.
✗ Branch 3 not taken.
|
336452 | ? enable_master_key_encryption(table) |
| 13870 |
1/2✓ Branch 0 taken 334520 times.
✗ Branch 1 not taken.
|
334521 | : enable_keyring_encryption(table, keyring_encryption_option); |
| 13871 | } | ||
| 13872 | |||
| 13873 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 348170 times.
|
348193 | if (err != DB_SUCCESS) { |
| 13874 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | dict_mem_table_free(table); |
| 13875 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | mem_heap_free(heap); |
| 13876 | 23 | goto error_ret; | |
| 13877 | } | ||
| 13878 | |||
| 13879 |
3/4✓ Branch 0 taken 348170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 153522 times.
✓ Branch 3 taken 194648 times.
|
348170 | if (table->is_temporary()) { |
| 13880 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 153521 times.
|
153522 | if (m_create_info->compress.length > 0) { |
| 13881 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 13882 | "InnoDB: Compression not supported for " | ||
| 13883 | "temporary tables"); | ||
| 13884 | |||
| 13885 | 1 | err = DB_UNSUPPORTED; | |
| 13886 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | dict_mem_table_free(table); |
| 13887 | } else { | ||
| 13888 | /* Get a new table ID */ | ||
| 13889 |
1/2✓ Branch 0 taken 153523 times.
✗ Branch 1 not taken.
|
153521 | dict_table_assign_new_id(table); |
| 13890 | |||
| 13891 | /* Create temp tablespace if configured. */ | ||
| 13892 | 153523 | KeyringEncryptionKeyIdInfo keyring_encryption_key_id; | |
| 13893 | 153523 | keyring_encryption_key_id.was_encryption_key_id_set = false; | |
| 13894 |
1/2✓ Branch 0 taken 153522 times.
✗ Branch 1 not taken.
|
153523 | err = dict_build_tablespace_for_table(table, m_create_info, m_trx, |
| 13895 | FIL_ENCRYPTION_DEFAULT, | ||
| 13896 | keyring_encryption_key_id); | ||
| 13897 | |||
| 13898 |
2/2✓ Branch 0 taken 153519 times.
✓ Branch 1 taken 3 times.
|
153522 | if (err == DB_SUCCESS) { |
| 13899 | /* Temp-table are maintained in memory and so | ||
| 13900 | can_be_evicted is false. */ | ||
| 13901 | mem_heap_t *temp_table_heap; | ||
| 13902 | |||
| 13903 |
1/2✓ Branch 0 taken 153519 times.
✗ Branch 1 not taken.
|
153519 | temp_table_heap = mem_heap_create(256, UT_LOCATION_HERE); |
| 13904 | |||
| 13905 | /* For intrinsic table (given that they are | ||
| 13906 | not shared beyond session scope), add | ||
| 13907 | it to session specific THD structure | ||
| 13908 | instead of adding it to dictionary cache. */ | ||
| 13909 |
3/4✓ Branch 0 taken 153519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110975 times.
✓ Branch 3 taken 42544 times.
|
153519 | if (table->is_intrinsic()) { |
| 13910 |
1/2✓ Branch 0 taken 110975 times.
✗ Branch 1 not taken.
|
110975 | add_table_to_thread_cache(table, temp_table_heap, m_thd); |
| 13911 | |||
| 13912 | } else { | ||
| 13913 |
1/2✓ Branch 0 taken 42544 times.
✗ Branch 1 not taken.
|
42544 | dict_table_add_system_columns(table, temp_table_heap); |
| 13914 | |||
| 13915 |
1/2✓ Branch 0 taken 42544 times.
✗ Branch 1 not taken.
|
42544 | dict_sys_mutex_enter(); |
| 13916 |
1/2✓ Branch 0 taken 42544 times.
✗ Branch 1 not taken.
|
42544 | dict_table_add_to_cache(table, false); |
| 13917 |
1/2✓ Branch 0 taken 42544 times.
✗ Branch 1 not taken.
|
42544 | dict_sys_mutex_exit(); |
| 13918 | } | ||
| 13919 | |||
| 13920 |
4/6✓ Branch 0 taken 153519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 153518 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
153519 | DBUG_EXECUTE_IF("ib_ddl_crash_during_create2", DBUG_SUICIDE();); |
| 13921 | |||
| 13922 |
1/2✓ Branch 0 taken 153518 times.
✗ Branch 1 not taken.
|
153518 | mem_heap_free(temp_table_heap); |
| 13923 | } else { | ||
| 13924 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | dict_mem_table_free(table); |
| 13925 | } | ||
| 13926 | } | ||
| 13927 | |||
| 13928 | } else { | ||
| 13929 | 194648 | const char *algorithm = m_create_info->compress.str; | |
| 13930 | |||
| 13931 | 194648 | err = DB_SUCCESS; | |
| 13932 | |||
| 13933 | 418183 | if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE) && | |
| 13934 |
6/6✓ Branch 0 taken 28887 times.
✓ Branch 1 taken 165761 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 28885 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 194646 times.
|
194650 | m_create_info->compress.length > 0 && |
| 13935 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | !Compression::is_none(algorithm)) { |
| 13936 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 13937 | "InnoDB: Compression not supported for " | ||
| 13938 | "shared tablespaces"); | ||
| 13939 | |||
| 13940 | 2 | algorithm = nullptr; | |
| 13941 | |||
| 13942 | 2 | err = DB_UNSUPPORTED; | |
| 13943 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | dict_mem_table_free(table); |
| 13944 | |||
| 13945 |
1/2✓ Branch 0 taken 194646 times.
✗ Branch 1 not taken.
|
194646 | } else if (Compression::validate(algorithm) != DB_SUCCESS || |
| 13946 |
6/6✓ Branch 0 taken 194645 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 193907 times.
✓ Branch 3 taken 738 times.
✓ Branch 4 taken 818 times.
✓ Branch 5 taken 193828 times.
|
388553 | m_form->s->row_type == ROW_TYPE_COMPRESSED || |
| 13947 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 193828 times.
|
193907 | m_create_info->key_block_size > 0) { |
| 13948 | 818 | algorithm = nullptr; | |
| 13949 | } | ||
| 13950 | |||
| 13951 | KeyringEncryptionKeyIdInfo keyring_encryption_key_id( | ||
| 13952 | 194648 | m_create_info->was_encryption_key_id_set, | |
| 13953 | 194648 | m_create_info->encryption_key_id); | |
| 13954 | |||
| 13955 |
2/2✓ Branch 0 taken 194646 times.
✓ Branch 1 taken 2 times.
|
194648 | if (err == DB_SUCCESS) { |
| 13956 |
1/2✓ Branch 0 taken 194609 times.
✗ Branch 1 not taken.
|
194646 | err = row_create_table_for_mysql(table, algorithm, m_create_info, m_trx, |
| 13957 | heap, | ||
| 13958 | keyring_encryption_option, | ||
| 13959 | keyring_encryption_key_id); | ||
| 13960 | |||
| 13961 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 194609 times.
|
194609 | if (err == DB_IO_NO_PUNCH_HOLE_FS) { |
| 13962 | ✗ | ut_ad(!dict_table_in_shared_tablespace(table)); | |
| 13963 | ✗ | my_error(ER_INNODB_COMPRESSION_FAILURE, MYF(0), | |
| 13964 | "Punch hole not supported by the filesystem or the tablespace " | ||
| 13965 | "page size is not large enough."); | ||
| 13966 | } | ||
| 13967 | |||
| 13968 |
4/4✓ Branch 0 taken 194595 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 121 times.
✓ Branch 3 taken 194474 times.
|
194609 | if (err == DB_SUCCESS && part_table_with_instant_cols) { |
| 13969 | /* Set phy_pos for system cols */ | ||
| 13970 | |||
| 13971 | 363 | auto fn = [&](uint32_t sys_col, const char *name) { | |
| 13972 | 363 | uint32_t phy_pos = UINT32_UNDEFINED; | |
| 13973 |
1/2✓ Branch 0 taken 363 times.
✗ Branch 1 not taken.
|
363 | dict_col_t *col = table->get_sys_col(sys_col); |
| 13974 |
1/2✓ Branch 0 taken 363 times.
✗ Branch 1 not taken.
|
363 | const dd::Column *old_part_col = dd_find_column(old_part_table, name); |
| 13975 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 262 times.
|
363 | if (old_part_col == nullptr) { |
| 13976 | /* If PK exists, DB_ROW_ID won't be part of table definition. */ | ||
| 13977 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 101 times.
|
101 | ut_ad(strcmp(name, "DB_ROW_ID") == 0); |
| 13978 | 101 | return; | |
| 13979 | } | ||
| 13980 | |||
| 13981 | 262 | const char *s = dd_column_key_strings[DD_INSTANT_PHYSICAL_POS]; | |
| 13982 |
4/8✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 262 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 262 times.
|
262 | ut_ad(old_part_col->se_private_data().exists(s)); |
| 13983 |
3/6✓ Branch 0 taken 262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 262 times.
✗ Branch 5 not taken.
|
262 | old_part_col->se_private_data().get(s, &phy_pos); |
| 13984 | 262 | col->set_phy_pos(phy_pos); | |
| 13985 | 121 | }; | |
| 13986 | |||
| 13987 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | fn(DATA_ROW_ID, "DB_ROW_ID"); |
| 13988 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | fn(DATA_TRX_ID, "DB_TRX_ID"); |
| 13989 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | fn(DATA_ROLL_PTR, "DB_ROLL_PTR"); |
| 13990 | |||
| 13991 | /* Add INSTANT DROP columns metadata */ | ||
| 13992 | 121 | IF_DEBUG(uint32_t row_version = 0;) | |
| 13993 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | fill_dict_dropped_columns(old_part_table, table, |
| 13994 | IF_DEBUG(row_version, ) heap); | ||
| 13995 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
|
121 | ut_ad(row_version <= table->current_row_version); |
| 13996 | } | ||
| 13997 | } | ||
| 13998 | |||
| 13999 |
4/6✓ Branch 0 taken 194611 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 194609 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
194611 | DBUG_EXECUTE_IF("ib_crash_during_create_for_encryption", DBUG_SUICIDE();); |
| 14000 | } | ||
| 14001 | |||
| 14002 |
1/2✓ Branch 0 taken 348131 times.
✗ Branch 1 not taken.
|
348131 | mem_heap_free(heap); |
| 14003 | |||
| 14004 |
2/4✓ Branch 0 taken 348131 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 348131 times.
|
348131 | DBUG_EXECUTE_IF("ib_create_err_tablespace_exist", |
| 14005 | err = DB_TABLESPACE_EXISTS;); | ||
| 14006 | |||
| 14007 |
2/4✓ Branch 0 taken 348131 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 348131 times.
|
348131 | if (err == DB_DUPLICATE_KEY || err == DB_TABLESPACE_EXISTS) { |
| 14008 | char display_name[FN_REFLEN]; | ||
| 14009 | char *buf_end = | ||
| 14010 | ✗ | innobase_convert_identifier(display_name, sizeof(display_name) - 1, | |
| 14011 | ✗ | m_table_name, strlen(m_table_name), m_thd); | |
| 14012 | |||
| 14013 | ✗ | *buf_end = '\0'; | |
| 14014 | |||
| 14015 | ✗ | my_error( | |
| 14016 | err == DB_DUPLICATE_KEY ? ER_TABLE_EXISTS_ERROR : ER_TABLESPACE_EXISTS, | ||
| 14017 | MYF(0), display_name); | ||
| 14018 | |||
| 14019 | ✗ | if (err == DB_DUPLICATE_KEY) { | |
| 14020 | /* 'this' may not be ready for get_dup_key(), see same | ||
| 14021 | error tweaking in rename_table(). */ | ||
| 14022 | ✗ | err = DB_ERROR; | |
| 14023 | } | ||
| 14024 | } | ||
| 14025 | |||
| 14026 |
4/4✓ Branch 0 taken 348111 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 465 times.
✓ Branch 3 taken 347646 times.
|
348131 | if (err == DB_SUCCESS && (m_flags2 & DICT_TF2_FTS)) { |
| 14027 |
1/2✓ Branch 0 taken 465 times.
✗ Branch 1 not taken.
|
465 | dict_sys_mutex_enter(); |
| 14028 |
1/2✓ Branch 0 taken 465 times.
✗ Branch 1 not taken.
|
465 | fts_optimize_add_table(table); |
| 14029 |
1/2✓ Branch 0 taken 465 times.
✗ Branch 1 not taken.
|
465 | dict_sys_mutex_exit(); |
| 14030 | } | ||
| 14031 | |||
| 14032 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 348111 times.
|
348131 | if (err == DB_SUCCESS) { |
| 14033 | 348111 | m_table = table; | |
| 14034 | } | ||
| 14035 | |||
| 14036 | 20 | error_ret: | |
| 14037 |
1/2✓ Branch 0 taken 348157 times.
✗ Branch 1 not taken.
|
348157 | return convert_error_code_to_mysql(err, m_flags, m_thd); |
| 14038 | 348184 | } | |
| 14039 | |||
| 14040 | template <typename Index> | ||
| 14041 | const dd::Index *get_my_dd_index(const Index *index); | ||
| 14042 | |||
| 14043 | template <> | ||
| 14044 | 379 | const dd::Index *get_my_dd_index<dd::Index>(const dd::Index *dd_index) { | |
| 14045 | 379 | return dd_index; | |
| 14046 | } | ||
| 14047 | |||
| 14048 | template <> | ||
| 14049 | ✗ | const dd::Index *get_my_dd_index<dd::Partition_index>( | |
| 14050 | const dd::Partition_index *dd_index) { | ||
| 14051 | ✗ | return (dd_index != nullptr) ? &dd_index->index() : nullptr; | |
| 14052 | } | ||
| 14053 | |||
| 14054 | /** Creates an index in an InnoDB database. */ | ||
| 14055 | 179566 | inline int create_index( | |
| 14056 | trx_t *trx, /*!< in: InnoDB transaction handle */ | ||
| 14057 | const TABLE *form, /*!< in: information on table | ||
| 14058 | columns and indexes */ | ||
| 14059 | uint32_t flags, /*!< in: InnoDB table flags */ | ||
| 14060 | const char *table_name, /*!< in: table name */ | ||
| 14061 | uint key_num, /*!< in: index number */ | ||
| 14062 | const dd::Table *dd_table) /*!< in: dd::Table for the table*/ | ||
| 14063 | { | ||
| 14064 | dict_index_t *index; | ||
| 14065 | int error; | ||
| 14066 | const KEY *key; | ||
| 14067 | ulint ind_type; | ||
| 14068 | ulint *field_lengths; | ||
| 14069 | 179566 | uint32_t srid = 0; | |
| 14070 | 179566 | bool has_srid = false; | |
| 14071 | 179566 | bool multi_val_idx = false; | |
| 14072 | |||
| 14073 |
1/2✓ Branch 0 taken 179566 times.
✗ Branch 1 not taken.
|
179566 | DBUG_TRACE; |
| 14074 | |||
| 14075 | 179566 | key = form->key_info + key_num; | |
| 14076 | |||
| 14077 | /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */ | ||
| 14078 |
2/4✓ Branch 0 taken 179566 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 179566 times.
|
179566 | ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0); |
| 14079 | |||
| 14080 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 179565 times.
|
179566 | if (key->key_length == 0) { |
| 14081 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error(ER_WRONG_KEY_COLUMN, MYF(0), key->key_part->field->field_name); |
| 14082 | 1 | return ER_WRONG_KEY_COLUMN; | |
| 14083 | } | ||
| 14084 | 179565 | ind_type = 0; | |
| 14085 |
2/2✓ Branch 0 taken 379 times.
✓ Branch 1 taken 179186 times.
|
179565 | if (key->flags & HA_SPATIAL) { |
| 14086 | 379 | ind_type = DICT_SPATIAL; | |
| 14087 |
2/2✓ Branch 0 taken 646 times.
✓ Branch 1 taken 178540 times.
|
179186 | } else if (key->flags & HA_FULLTEXT) { |
| 14088 | 646 | ind_type = DICT_FTS; | |
| 14089 | } | ||
| 14090 | |||
| 14091 |
2/2✓ Branch 0 taken 379 times.
✓ Branch 1 taken 179186 times.
|
179565 | if (ind_type == DICT_SPATIAL) { |
| 14092 |
2/2✓ Branch 0 taken 121 times.
✓ Branch 1 taken 258 times.
|
379 | ulint dd_index_num = key_num + ((form->s->primary_key == MAX_KEY) ? 1 : 0); |
| 14093 | |||
| 14094 |
2/4✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
|
379 | const auto *dd_index_auto = dd_table->indexes()[dd_index_num]; |
| 14095 | |||
| 14096 |
1/2✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
|
379 | const dd::Index *dd_index = get_my_dd_index(dd_index_auto); |
| 14097 |
2/4✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 379 times.
|
379 | ut_ad(dd_index->name() == key->name); |
| 14098 | |||
| 14099 | size_t geom_col_idx; | ||
| 14100 |
2/4✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
|
379 | for (geom_col_idx = 0; geom_col_idx < dd_index->elements().size(); |
| 14101 | ++geom_col_idx) { | ||
| 14102 |
5/10✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 379 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 379 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 379 times.
✗ Branch 9 not taken.
|
379 | if (!dd_index->elements()[geom_col_idx]->column().is_se_hidden()) break; |
| 14103 | } | ||
| 14104 |
3/6✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 379 times.
✗ Branch 5 not taken.
|
379 | const dd::Column &col = dd_index->elements()[geom_col_idx]->column(); |
| 14105 |
1/2✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
|
379 | has_srid = col.srs_id().has_value(); |
| 14106 |
4/6✓ Branch 0 taken 368 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 368 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 368 times.
✗ Branch 5 not taken.
|
379 | srid = has_srid ? col.srs_id().value() : 0; |
| 14107 | } | ||
| 14108 | |||
| 14109 |
2/2✓ Branch 0 taken 1025 times.
✓ Branch 1 taken 178540 times.
|
179565 | if (ind_type != 0) { |
| 14110 | 2050 | index = dict_mem_index_create(table_name, key->name, 0, ind_type, | |
| 14111 |
1/2✓ Branch 0 taken 1025 times.
✗ Branch 1 not taken.
|
1025 | key->user_defined_key_parts); |
| 14112 | |||
| 14113 |
2/2✓ Branch 0 taken 1157 times.
✓ Branch 1 taken 1025 times.
|
2182 | for (ulint i = 0; i < key->user_defined_key_parts; i++) { |
| 14114 | 1157 | KEY_PART_INFO *key_part = key->key_part + i; | |
| 14115 | |||
| 14116 | /* We do not support special (Fulltext or Spatial) | ||
| 14117 | index on virtual columns */ | ||
| 14118 |
3/4✓ Branch 0 taken 46 times.
✓ Branch 1 taken 1111 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
|
1157 | if (innobase_is_v_fld(key_part->field)) { |
| 14119 | ✗ | ut_d(ut_error); | |
| 14120 | ut_o(return HA_ERR_UNSUPPORTED); | ||
| 14121 | } | ||
| 14122 | |||
| 14123 | 1157 | index->add_field(key_part->field->field_name, 0, | |
| 14124 |
1/2✓ Branch 0 taken 1157 times.
✗ Branch 1 not taken.
|
1157 | !(key_part->key_part_flag & HA_REVERSE_SORT)); |
| 14125 | } | ||
| 14126 | |||
| 14127 |
2/2✓ Branch 0 taken 379 times.
✓ Branch 1 taken 646 times.
|
1025 | if (ind_type == DICT_SPATIAL) { |
| 14128 | 379 | index->srid_is_valid = has_srid; | |
| 14129 | 379 | index->srid = srid; | |
| 14130 |
1/2✓ Branch 0 taken 379 times.
✗ Branch 1 not taken.
|
379 | index->rtr_srs.reset(fetch_srs(index->srid)); |
| 14131 | } | ||
| 14132 | |||
| 14133 |
2/4✓ Branch 0 taken 1025 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1025 times.
✗ Branch 3 not taken.
|
1025 | return convert_error_code_to_mysql( |
| 14134 | row_create_index_for_mysql(index, trx, nullptr, nullptr), flags, | ||
| 14135 | 1025 | nullptr); | |
| 14136 | } | ||
| 14137 | |||
| 14138 | 178540 | ind_type = 0; | |
| 14139 | |||
| 14140 |
2/2✓ Branch 0 taken 105666 times.
✓ Branch 1 taken 72874 times.
|
178540 | if (key_num == form->s->primary_key) { |
| 14141 | 105666 | ind_type |= DICT_CLUSTERED; | |
| 14142 | } | ||
| 14143 | |||
| 14144 |
2/2✓ Branch 0 taken 139878 times.
✓ Branch 1 taken 38662 times.
|
178540 | if (key->flags & HA_NOSAME) { |
| 14145 | 139878 | ind_type |= DICT_UNIQUE; | |
| 14146 | } | ||
| 14147 | |||
| 14148 | 357080 | field_lengths = (ulint *)my_malloc( | |
| 14149 |
1/2✓ Branch 0 taken 178540 times.
✗ Branch 1 not taken.
|
178540 | PSI_INSTRUMENT_ME, key->user_defined_key_parts * sizeof *field_lengths, |
| 14150 | MYF(MY_FAE)); | ||
| 14151 | |||
| 14152 | /* We pass 0 as the space id, and determine at a lower level the space | ||
| 14153 | id where to store the table */ | ||
| 14154 | |||
| 14155 | 357080 | index = dict_mem_index_create(table_name, key->name, 0, ind_type, | |
| 14156 |
1/2✓ Branch 0 taken 178540 times.
✗ Branch 1 not taken.
|
178540 | key->user_defined_key_parts); |
| 14157 | |||
| 14158 |
1/2✓ Branch 0 taken 178540 times.
✗ Branch 1 not taken.
|
178540 | innodb_session_t *&priv = thd_to_innodb_session(trx->mysql_thd); |
| 14159 |
1/2✓ Branch 0 taken 178539 times.
✗ Branch 1 not taken.
|
178540 | dict_table_t *handler = priv->lookup_table_handler(table_name); |
| 14160 | |||
| 14161 |
2/2✓ Branch 0 taken 2811 times.
✓ Branch 1 taken 175728 times.
|
178539 | if (handler != nullptr) { |
| 14162 | /* This setting will enforce SQL NULL == SQL NULL. | ||
| 14163 | For now this is turned-on for intrinsic tables | ||
| 14164 | only but can be turned on for other tables if needed arises. */ | ||
| 14165 | 2811 | index->nulls_equal = (key->flags & HA_NULL_ARE_EQUAL) ? true : false; | |
| 14166 | |||
| 14167 | /* Disable use of AHI for intrinsic table indexes as AHI | ||
| 14168 | validates the predicated entry using index-id which has to be | ||
| 14169 | system-wide unique that is not the case with indexes of | ||
| 14170 | intrinsic table for performance reason. | ||
| 14171 | Also given the lifetime of these tables and frequent delete | ||
| 14172 | and update AHI would not help on performance front as it does | ||
| 14173 | with normal tables. */ | ||
| 14174 | 2811 | index->disable_ahi = true; | |
| 14175 | } | ||
| 14176 | |||
| 14177 |
2/2✓ Branch 0 taken 248182 times.
✓ Branch 1 taken 178540 times.
|
426722 | for (ulint i = 0; i < key->user_defined_key_parts; i++) { |
| 14178 | 248182 | KEY_PART_INFO *key_part = key->key_part + i; | |
| 14179 | ulint prefix_len; | ||
| 14180 | ulint col_type; | ||
| 14181 | ulint is_unsigned; | ||
| 14182 | |||
| 14183 | /* (The flag HA_PART_KEY_SEG denotes in MySQL a | ||
| 14184 | column prefix field in an index: we only store a | ||
| 14185 | specified number of first bytes of the column to | ||
| 14186 | the index field.) The flag does not seem to be | ||
| 14187 | properly set by MySQL. Let us fall back on testing | ||
| 14188 | the length of the key part versus the column. | ||
| 14189 | We first reach to the table's column; if the index is on a | ||
| 14190 | prefix, key_part->field is not the table's column (it's a | ||
| 14191 | "fake" field forged in open_table_from_share() with length | ||
| 14192 | equal to the length of the prefix); so we have to go to | ||
| 14193 | form->fied. */ | ||
| 14194 | 248182 | Field *field = form->field[key_part->field->field_index()]; | |
| 14195 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 248183 times.
|
248183 | if (field == nullptr) ut_error; |
| 14196 | |||
| 14197 | 248183 | const char *field_name = key_part->field->field_name; | |
| 14198 |
6/8✓ Branch 0 taken 3545 times.
✓ Branch 1 taken 244638 times.
✓ Branch 2 taken 3545 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3545 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3545 times.
✓ Branch 7 taken 244638 times.
|
248183 | if (handler != nullptr && handler->is_intrinsic()) { |
| 14199 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 3545 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3545 times.
|
3545 | ut_ad(!innobase_is_v_fld(key_part->field)); |
| 14200 | ulint col_no = | ||
| 14201 |
2/4✓ Branch 0 taken 3545 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3545 times.
✗ Branch 3 not taken.
|
3545 | dict_col_get_no(handler->get_col(key_part->field->field_index())); |
| 14202 |
1/2✓ Branch 0 taken 3545 times.
✗ Branch 1 not taken.
|
3545 | field_name = handler->get_col_name(col_no); |
| 14203 | } | ||
| 14204 | |||
| 14205 |
1/2✓ Branch 0 taken 248182 times.
✗ Branch 1 not taken.
|
248183 | col_type = get_innobase_type_from_mysql_type(&is_unsigned, key_part->field); |
| 14206 | |||
| 14207 | /* Multi-value prefix index is not supported. */ | ||
| 14208 |
7/8✓ Branch 0 taken 248182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 247939 times.
✓ Branch 3 taken 243 times.
✓ Branch 4 taken 242894 times.
✓ Branch 5 taken 5046 times.
✓ Branch 6 taken 6072 times.
✓ Branch 7 taken 242110 times.
|
739015 | if (!innobase_is_multi_value_fld(key_part->field) && |
| 14209 | 247939 | (DATA_LARGE_MTYPE(col_type) || | |
| 14210 |
3/4✓ Branch 0 taken 242893 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37530 times.
✓ Branch 3 taken 205363 times.
|
242894 | (key_part->length < field->pack_length() && |
| 14211 |
3/4✓ Branch 0 taken 37530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37011 times.
✓ Branch 3 taken 519 times.
|
37530 | field->type() != MYSQL_TYPE_VARCHAR) || |
| 14212 |
3/4✓ Branch 0 taken 242374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37011 times.
✓ Branch 3 taken 205363 times.
|
242374 | (field->type() == MYSQL_TYPE_VARCHAR && |
| 14213 | 37011 | key_part->length < | |
| 14214 |
4/6✓ Branch 0 taken 37011 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37011 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 507 times.
✓ Branch 5 taken 36504 times.
|
37011 | field->pack_length() - field->get_length_bytes()))) { |
| 14215 |
1/2✓ Branch 0 taken 6072 times.
✗ Branch 1 not taken.
|
6072 | switch (col_type) { |
| 14216 | 6072 | default: | |
| 14217 | 6072 | prefix_len = key_part->length; | |
| 14218 | 6072 | break; | |
| 14219 | ✗ | case DATA_INT: | |
| 14220 | case DATA_FLOAT: | ||
| 14221 | case DATA_DOUBLE: | ||
| 14222 | case DATA_DECIMAL: | ||
| 14223 | ✗ | log_errlog(ERROR_LEVEL, ER_WRONG_TYPE_FOR_COLUMN_PREFIX_IDX_FLD, | |
| 14224 | table_name, key_part->field->field_name); | ||
| 14225 | |||
| 14226 | ✗ | prefix_len = 0; | |
| 14227 | } | ||
| 14228 | } else { | ||
| 14229 | 242110 | prefix_len = 0; | |
| 14230 | } | ||
| 14231 | |||
| 14232 | 248182 | field_lengths[i] = key_part->length; | |
| 14233 | |||
| 14234 |
7/10✓ Branch 0 taken 5420 times.
✓ Branch 1 taken 242762 times.
✓ Branch 2 taken 1029 times.
✓ Branch 3 taken 4391 times.
✓ Branch 4 taken 243792 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 243792 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 248183 times.
|
248182 | ut_ad(!(!innobase_is_v_fld(key_part->field) && |
| 14235 | innobase_is_multi_value_fld(key_part->field))); | ||
| 14236 | |||
| 14237 |
4/4✓ Branch 0 taken 5420 times.
✓ Branch 1 taken 242763 times.
✓ Branch 2 taken 4391 times.
✓ Branch 3 taken 1029 times.
|
248183 | if (innobase_is_v_fld(key_part->field)) { |
| 14238 | 4391 | index->type |= DICT_VIRTUAL; | |
| 14239 | |||
| 14240 |
3/4✓ Branch 0 taken 4391 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 243 times.
✓ Branch 3 taken 4148 times.
|
4391 | if (innobase_is_multi_value_fld(key_part->field)) { |
| 14241 | 243 | index->type |= DICT_MULTI_VALUE; | |
| 14242 | } | ||
| 14243 | } | ||
| 14244 | |||
| 14245 | 248183 | index->add_field(field_name, prefix_len, | |
| 14246 |
1/2✓ Branch 0 taken 248183 times.
✗ Branch 1 not taken.
|
248183 | !(key_part->key_part_flag & HA_REVERSE_SORT)); |
| 14247 | } | ||
| 14248 | |||
| 14249 |
3/6✓ Branch 0 taken 178540 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 178540 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 178540 times.
|
178540 | ut_ad(key->flags & HA_FULLTEXT || !(index->type & DICT_FTS)); |
| 14250 | |||
| 14251 | 178540 | multi_val_idx = ((index->type & DICT_MULTI_VALUE) == DICT_MULTI_VALUE); | |
| 14252 | |||
| 14253 | /* Even though we've defined max_supported_key_part_length, we | ||
| 14254 | still do our own checking using field_lengths to be absolutely | ||
| 14255 | sure we don't create too long indexes. */ | ||
| 14256 | |||
| 14257 |
2/4✓ Branch 0 taken 178457 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 178457 times.
✗ Branch 3 not taken.
|
178540 | error = convert_error_code_to_mysql( |
| 14258 | row_create_index_for_mysql(index, trx, field_lengths, handler), flags, | ||
| 14259 | nullptr); | ||
| 14260 | |||
| 14261 | /* For multi-value virtual index, we need to adjust indexed col length */ | ||
| 14262 |
4/4✓ Branch 0 taken 178444 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 243 times.
✓ Branch 3 taken 178201 times.
|
178457 | if (error == 0 && multi_val_idx) { |
| 14263 |
1/2✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
|
243 | dict_table_t *new_table = dd_table_open_on_name_in_mem(table_name, false); |
| 14264 | |||
| 14265 | 243 | dict_index_t *last_index = UT_LIST_GET_LAST(new_table->indexes); | |
| 14266 |
2/2✓ Branch 0 taken 523 times.
✓ Branch 1 taken 243 times.
|
766 | for (unsigned int i = 0; i < last_index->n_fields; i++) { |
| 14267 |
4/4✓ Branch 0 taken 243 times.
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 161 times.
✓ Branch 3 taken 362 times.
|
766 | if (last_index->fields[i].col->is_multi_value() && |
| 14268 |
2/2✓ Branch 0 taken 161 times.
✓ Branch 1 taken 82 times.
|
243 | (last_index->fields[i].fixed_len != 0)) { |
| 14269 | 161 | last_index->fields[i].fixed_len = field_lengths[i]; | |
| 14270 | } | ||
| 14271 | } | ||
| 14272 | |||
| 14273 |
1/2✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
|
243 | dd_table_close(new_table, nullptr, nullptr, false); |
| 14274 | } | ||
| 14275 | |||
| 14276 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 178444 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
178457 | if (error && handler != nullptr) { |
| 14277 | ✗ | priv->unregister_table_handler(table_name); | |
| 14278 | } | ||
| 14279 | |||
| 14280 |
1/2✓ Branch 0 taken 178457 times.
✗ Branch 1 not taken.
|
178457 | my_free(field_lengths); |
| 14281 | |||
| 14282 | 178457 | return error; | |
| 14283 | 179483 | } | |
| 14284 | |||
| 14285 | /** Creates an index to an InnoDB table when the user has defined no | ||
| 14286 | primary index. */ | ||
| 14287 | 242444 | inline int create_clustered_index_when_no_primary( | |
| 14288 | trx_t *trx, /*!< in: InnoDB transaction handle */ | ||
| 14289 | uint32_t flags, /*!< in: InnoDB table flags */ | ||
| 14290 | const char *table_name) /*!< in: table name */ | ||
| 14291 | { | ||
| 14292 | dict_index_t *index; | ||
| 14293 | dberr_t error; | ||
| 14294 | |||
| 14295 | /* We pass 0 as the space id, and determine at a lower level the space | ||
| 14296 | id where to store the table */ | ||
| 14297 | 242444 | index = dict_mem_index_create(table_name, innobase_index_reserve_name, 0, | |
| 14298 | DICT_CLUSTERED, 0); | ||
| 14299 | |||
| 14300 | 242444 | innodb_session_t *&priv = thd_to_innodb_session(trx->mysql_thd); | |
| 14301 | |||
| 14302 | 242444 | dict_table_t *handler = priv->lookup_table_handler(table_name); | |
| 14303 | |||
| 14304 |
2/2✓ Branch 0 taken 110275 times.
✓ Branch 1 taken 132169 times.
|
242444 | if (handler != nullptr) { |
| 14305 | /* Disable use of AHI for intrinsic table indexes as AHI | ||
| 14306 | validates the predicated entry using index-id which has to be | ||
| 14307 | system-wide unique that is not the case with indexes of | ||
| 14308 | intrinsic table for performance reason. | ||
| 14309 | Also given the lifetime of these tables and frequent delete | ||
| 14310 | and update AHI would not help on performance front as it does | ||
| 14311 | with normal tables. */ | ||
| 14312 | 110275 | index->disable_ahi = true; | |
| 14313 | } | ||
| 14314 | |||
| 14315 | 242444 | error = row_create_index_for_mysql(index, trx, nullptr, handler); | |
| 14316 | |||
| 14317 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 242431 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
242444 | if (error != DB_SUCCESS && handler != nullptr) { |
| 14318 | ✗ | priv->unregister_table_handler(table_name); | |
| 14319 | } | ||
| 14320 | |||
| 14321 | 242444 | return (convert_error_code_to_mysql(error, flags, nullptr)); | |
| 14322 | } | ||
| 14323 | |||
| 14324 | 26 | void create_table_info_t::log_error_invalid_location(std::string &msg, | |
| 14325 | bool ignore) { | ||
| 14326 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 18 times.
|
26 | if (ignore) { |
| 14327 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | THD *thd = current_thd; |
| 14328 | |||
| 14329 | 8 | constexpr char ignored_msg[] = | |
| 14330 | " The DATA DIRECTORY location will be ignored and the" | ||
| 14331 | " file will be put into the default datadir location."; | ||
| 14332 | |||
| 14333 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | msg.append(ignored_msg); |
| 14334 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_FILE_NAME, |
| 14335 | "%s", msg.c_str()); | ||
| 14336 | |||
| 14337 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | ib::warn(ER_IB_MSG_INVALID_LOCATION_FOR_TABLE, m_table_name, msg.c_str()); |
| 14338 | } else { | ||
| 14339 | 18 | my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str()); | |
| 14340 | |||
| 14341 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLE, m_table_name, msg.c_str()); |
| 14342 | } | ||
| 14343 | 26 | } | |
| 14344 | |||
| 14345 | 878 | bool create_table_info_t::create_option_data_directory_is_valid(bool ignore) { | |
| 14346 | 878 | bool is_valid = true; | |
| 14347 | |||
| 14348 |
3/6✓ Branch 0 taken 878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 878 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 878 times.
|
878 | ut_ad(m_create_info->data_file_name != nullptr && |
| 14349 | *m_create_info->data_file_name != '\0'); | ||
| 14350 | |||
| 14351 | /* Use DATA DIRECTORY only with file-per-table. */ | ||
| 14352 |
3/4✓ Branch 0 taken 878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 870 times.
|
878 | if (!m_use_shared_space && !m_allow_file_per_table) { |
| 14353 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, |
| 14354 | "InnoDB: DATA DIRECTORY requires" | ||
| 14355 | " innodb_file_per_table."); | ||
| 14356 | 8 | is_valid = false; | |
| 14357 | } | ||
| 14358 | |||
| 14359 | /* Do not use DATA DIRECTORY with TEMPORARY TABLE. */ | ||
| 14360 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 872 times.
|
878 | if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { |
| 14361 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, |
| 14362 | "InnoDB: DATA DIRECTORY cannot be used" | ||
| 14363 | " for TEMPORARY tables."); | ||
| 14364 | 6 | is_valid = false; | |
| 14365 | } | ||
| 14366 | |||
| 14367 | /* We checked previously for a conflicting DATA DIRECTORY mixed | ||
| 14368 | with TABLESPACE in create_option_tablespace_is_valid(). | ||
| 14369 | An ALTER TABLE statement might have both if it is being moved. | ||
| 14370 | So if m_tablespace is set, don't check the existing data_file_name. */ | ||
| 14371 |
2/2✓ Branch 0 taken 192 times.
✓ Branch 1 taken 686 times.
|
878 | if (m_create_info->tablespace != nullptr) { |
| 14372 | 192 | return (is_valid); | |
| 14373 | } | ||
| 14374 | |||
| 14375 | #ifndef UNIV_HOTBACKUP | ||
| 14376 | /* Validate the directory location. */ | ||
| 14377 | 686 | bool suffixed_table_name = !m_partition; | |
| 14378 |
3/6✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 686 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 686 times.
✗ Branch 5 not taken.
|
686 | char *filepath = Fil_path::make(m_create_info->data_file_name, m_table_name, |
| 14379 | IBD, suffixed_table_name); | ||
| 14380 |
1/2✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
|
686 | size_t dirname_len = dirname_length(filepath); |
| 14381 |
1/2✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
|
686 | Fil_path dirpath(filepath, dirname_len, true); |
| 14382 | |||
| 14383 | /* Do not allow the file to be created in a unique undo directory. */ | ||
| 14384 |
6/8✓ Branch 0 taken 43 times.
✓ Branch 1 taken 643 times.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 683 times.
|
729 | if (MySQL_undo_path_is_unique && (MySQL_undo_path.is_same_as(dirpath) || |
| 14385 |
3/4✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 40 times.
|
43 | MySQL_undo_path.is_ancestor(dirpath))) { |
| 14386 | std::string msg( | ||
| 14387 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | "The DATA DIRECTORY location cannot be the undo directory."); |
| 14388 | |||
| 14389 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | log_error_invalid_location(msg, ignore); |
| 14390 | |||
| 14391 | 3 | is_valid = false; | |
| 14392 | 3 | } | |
| 14393 | |||
| 14394 | /* Do not allow a file-per-table tablespace in the datadir. | ||
| 14395 | In order to be located in the datadir, one must use a schama name | ||
| 14396 | identical to the datadir directory and the datadir parent must be | ||
| 14397 | used as the DATA DIRECTORY.*/ | ||
| 14398 |
1/2✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
|
686 | bool in_datadir = MySQL_datadir_path.is_same_as(dirpath); |
| 14399 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 684 times.
|
686 | if (in_datadir) { |
| 14400 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | std::string msg("The DATA DIRECTORY location cannot be the datadir."); |
| 14401 | |||
| 14402 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | log_error_invalid_location(msg, ignore); |
| 14403 | |||
| 14404 | 2 | is_valid = false; | |
| 14405 | 2 | } | |
| 14406 | |||
| 14407 | /* Do not allow a datafile outside the known directories. */ | ||
| 14408 |
1/2✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
|
686 | bool under_datadir = MySQL_datadir_path.is_ancestor(dirpath); |
| 14409 | bool in_known_location = | ||
| 14410 |
6/8✓ Branch 0 taken 684 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 684 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 684 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 663 times.
✓ Branch 7 taken 21 times.
|
686 | (in_datadir || under_datadir) ? true : fil_path_is_known(dirpath.path()); |
| 14411 | |||
| 14412 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 665 times.
|
686 | if (!in_known_location) { |
| 14413 | std::string msg( | ||
| 14414 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | "The DATA DIRECTORY location must be in a known directory."); |
| 14415 | |||
| 14416 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | log_error_invalid_location(msg, ignore); |
| 14417 | |||
| 14418 | 21 | is_valid = false; | |
| 14419 | 21 | } | |
| 14420 | |||
| 14421 | 686 | ut::free(filepath); | |
| 14422 | #endif /* UNIV_HOTBACKUP */ | ||
| 14423 | |||
| 14424 | 686 | return (is_valid); | |
| 14425 | 686 | } | |
| 14426 | |||
| 14427 | /** Validate the tablespace name provided for a tablespace DDL | ||
| 14428 | @param[in] ts_command tablespace command type | ||
| 14429 | @param[in] name A proposed tablespace name | ||
| 14430 | @return MySQL handler error code like HA_... */ | ||
| 14431 | 420289 | static int validate_tablespace_name(ts_command_type ts_command, | |
| 14432 | const char *name) { | ||
| 14433 | 420289 | int err = 0; | |
| 14434 | |||
| 14435 | /* This prefix is reserved by InnoDB for use in internal tablespace | ||
| 14436 | names. */ | ||
| 14437 | 420289 | const char reserved_space_name_prefix[] = "innodb_"; | |
| 14438 | |||
| 14439 | /* Validation at the SQL layer should already be completed at this | ||
| 14440 | stage. Re-assert that the length is valid. */ | ||
| 14441 |
2/4✓ Branch 0 taken 420289 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 420289 times.
|
420289 | if (validate_tablespace_name_length(name)) { |
| 14442 | ✗ | my_printf_error(ER_WRONG_TABLESPACE_NAME, | |
| 14443 | "InnoDB: Tablespace name `%s` is too long.", MYF(0), name); | ||
| 14444 | ✗ | return (HA_WRONG_CREATE_OPTION); | |
| 14445 | } | ||
| 14446 | |||
| 14447 | /* The tablespace name cannot start with `innodb_`. */ | ||
| 14448 |
2/2✓ Branch 0 taken 21888 times.
✓ Branch 1 taken 398401 times.
|
420289 | if (strlen(name) >= sizeof(reserved_space_name_prefix) - 1 && |
| 14449 |
2/2✓ Branch 0 taken 1976 times.
✓ Branch 1 taken 19912 times.
|
21888 | 0 == memcmp(name, reserved_space_name_prefix, |
| 14450 | sizeof(reserved_space_name_prefix) - 1)) { | ||
| 14451 | /* Use a different message for reserved names */ | ||
| 14452 |
2/2✓ Branch 0 taken 1032 times.
✓ Branch 1 taken 944 times.
|
1976 | if (0 == strcmp(name, dict_sys_t::s_file_per_table_name) || |
| 14453 |
2/2✓ Branch 0 taken 308 times.
✓ Branch 1 taken 724 times.
|
1032 | 0 == strcmp(name, dict_sys_t::s_sys_space_name) || |
| 14454 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 271 times.
|
308 | 0 == strcmp(name, dict_sys_t::s_temp_space_name)) { |
| 14455 | /* Allow these names if the caller is putting a | ||
| 14456 | table into one of these by CREATE/ALTER TABLE */ | ||
| 14457 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1688 times.
|
1705 | if (ts_command != TS_CMD_NOT_DEFINED) { |
| 14458 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 14459 | "InnoDB: `%s` is a reserved" | ||
| 14460 | " tablespace name.", | ||
| 14461 | MYF(0), name); | ||
| 14462 | 17 | err = HA_WRONG_CREATE_OPTION; | |
| 14463 | } | ||
| 14464 | } else { | ||
| 14465 | /* Allow any undo tablespace to be set active or inactive. | ||
| 14466 | And any undo tablespace can be dropped except the default two | ||
| 14467 | implicit spaces. All other DDL should not work on tablespaces | ||
| 14468 | that start with "innodb_". */ | ||
| 14469 | 271 | bool allow = | |
| 14470 |
4/4✓ Branch 0 taken 27 times.
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 20 times.
|
278 | (ts_command == ALTER_UNDO_TABLESPACE || |
| 14471 | 7 | (ts_command == DROP_UNDO_TABLESPACE && | |
| 14472 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | 0 != strcmp(name, dict_sys_t::s_default_undo_space_name_1) && |
| 14473 | ✗ | 0 != strcmp(name, dict_sys_t::s_default_undo_space_name_2))); | |
| 14474 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 244 times.
|
271 | if (!allow) { |
| 14475 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 14476 | "InnoDB: Tablespace names starting" | ||
| 14477 | " with `%s` are reserved.", | ||
| 14478 | MYF(0), reserved_space_name_prefix); | ||
| 14479 | 27 | err = HA_WRONG_CREATE_OPTION; | |
| 14480 | } | ||
| 14481 | } | ||
| 14482 |
2/2✓ Branch 0 taken 392483 times.
✓ Branch 1 taken 25830 times.
|
420289 | } else if (0 == strcmp(name, dict_sys_t::s_dd_space_name)) { |
| 14483 | /* mysql tablespace can't be created or dropped */ | ||
| 14484 |
4/4✓ Branch 0 taken 392479 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 392472 times.
|
392483 | if (ts_command == CREATE_TABLESPACE || ts_command == DROP_TABLESPACE) { |
| 14485 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 14486 | "InnoDB: `mysql` is a reserved" | ||
| 14487 | " tablespace name.", | ||
| 14488 | MYF(0)); | ||
| 14489 | 11 | err = HA_WRONG_CREATE_OPTION; | |
| 14490 | } | ||
| 14491 | } | ||
| 14492 | |||
| 14493 | /* The tablespace name cannot contain a '/'. */ | ||
| 14494 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 420282 times.
|
420289 | if (memchr(name, '/', strlen(name)) != nullptr) { |
| 14495 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 14496 | "InnoDB: A general tablespace name cannot" | ||
| 14497 | " contain '/'.", | ||
| 14498 | MYF(0)); | ||
| 14499 | 7 | err = HA_WRONG_CREATE_OPTION; | |
| 14500 | } | ||
| 14501 | |||
| 14502 | 420289 | return (err); | |
| 14503 | } | ||
| 14504 | |||
| 14505 | 362424 | bool innobase_is_valid_tablespace_name(ts_command_type ts_cmd, | |
| 14506 | const char *name) { | ||
| 14507 | 362424 | return (0 == validate_tablespace_name(ts_cmd, name)); | |
| 14508 | } | ||
| 14509 | |||
| 14510 | /** Validate TABLESPACE option. | ||
| 14511 | @return true if valid, false if not. */ | ||
| 14512 | 381168 | bool create_table_info_t::create_option_tablespace_is_valid() { | |
| 14513 | 381168 | bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 14514 | 381168 | bool is_file_per_table = tablespace_is_file_per_table(m_create_info); | |
| 14515 | 381168 | bool is_general_space = tablespace_is_general_space(m_create_info); | |
| 14516 | 381168 | bool is_temp_space = | |
| 14517 |
2/2✓ Branch 0 taken 71267 times.
✓ Branch 1 taken 309901 times.
|
452435 | (m_create_info->tablespace && |
| 14518 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 71250 times.
|
71267 | strcmp(m_create_info->tablespace, dict_sys_t::s_temp_space_name) == 0); |
| 14519 | |||
| 14520 | /* Do not allow creation of a temp table | ||
| 14521 | with innodb_file_per_table or innodb_temporary option. */ | ||
| 14522 |
6/6✓ Branch 0 taken 153562 times.
✓ Branch 1 taken 227606 times.
✓ Branch 2 taken 153560 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 153547 times.
|
381168 | if (is_temp && (is_file_per_table || is_temp_space)) { |
| 14523 |
7/8✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 14 times.
|
15 | if (THDVAR(m_thd, strict_mode) && is_file_per_table) { |
| 14524 | 1 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 14525 | "InnoDB: TABLESPACE=%s option" | ||
| 14526 | " is disallowed for temporary tables" | ||
| 14527 | " with INNODB_STRICT_MODE=ON. This option is" | ||
| 14528 | " deprecated and will be removed in a future release", | ||
| 14529 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | MYF(0), m_create_info->tablespace); |
| 14530 | 1 | return false; | |
| 14531 | } | ||
| 14532 | |||
| 14533 | /* STRICT mode turned off. Proceed with the execution with | ||
| 14534 | a deprecation warning */ | ||
| 14535 | 14 | push_warning_printf( | |
| 14536 | m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14537 | "InnoDB: TABLESPACE=%s option is ignored. All temporary tables" | ||
| 14538 | " are created in a session temporary tablespace. This option" | ||
| 14539 | " is deprecated and will be removed in a future release.", | ||
| 14540 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | m_create_info->tablespace); |
| 14541 | } | ||
| 14542 | |||
| 14543 | /* Check the encryption option validity. */ | ||
| 14544 |
6/6✓ Branch 0 taken 69374 times.
✓ Branch 1 taken 311793 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 69364 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 381157 times.
|
450541 | if (m_create_info->encrypt_type.str != nullptr && |
| 14545 | 69374 | Encryption::validate(m_create_info->encrypt_type.str) == DB_UNSUPPORTED) { | |
| 14546 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); |
| 14547 | 10 | return false; | |
| 14548 | } | ||
| 14549 | |||
| 14550 |
2/2✓ Branch 0 taken 337659 times.
✓ Branch 1 taken 43498 times.
|
381157 | if (!m_use_shared_space) { |
| 14551 |
2/2✓ Branch 0 taken 158080 times.
✓ Branch 1 taken 179579 times.
|
337659 | if (!m_use_file_per_table) { |
| 14552 |
2/2✓ Branch 0 taken 1123 times.
✓ Branch 1 taken 156957 times.
|
158080 | if (m_create_info->encrypt_type.str != nullptr && |
| 14553 |
4/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1103 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 11 times.
|
1123 | m_create_info->explicit_encryption && is_temp) { |
| 14554 | /* Temporary tablespace is being used for table */ | ||
| 14555 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 14556 | "InnoDB: ENCRYPTION is not accepted" | ||
| 14557 | " for temporary tablespace. For temporary tablespace" | ||
| 14558 | " encryption please use innodb_temp_tablespace_encrypt" | ||
| 14559 | " variable.", | ||
| 14560 | MYF(0)); | ||
| 14561 | 9 | return false; | |
| 14562 | } | ||
| 14563 | |||
| 14564 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 158070 times.
|
158071 | if (m_create_info->m_implicit_tablespace_autoextend_size > 0) { |
| 14565 | /* AUTOEXTEND_SIZE is not allowed for system tablespace. */ | ||
| 14566 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 14567 | "InnoDB : AUTOEXTEND_SIZE is not accepted" | ||
| 14568 | " for system tablespace.", | ||
| 14569 | MYF(0)); | ||
| 14570 | 1 | return false; | |
| 14571 | } | ||
| 14572 | } | ||
| 14573 | |||
| 14574 | /* Validate autoextend_size attribute value. */ | ||
| 14575 |
4/4✓ Branch 0 taken 5510 times.
✓ Branch 1 taken 332139 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 337635 times.
|
343159 | if (m_create_info->m_implicit_tablespace_autoextend_size > 0 && |
| 14576 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 5496 times.
|
5510 | validate_autoextend_size_value( |
| 14577 |
1/2✓ Branch 0 taken 5510 times.
✗ Branch 1 not taken.
|
5510 | m_create_info->m_implicit_tablespace_autoextend_size) != |
| 14578 | DB_SUCCESS) { | ||
| 14579 | 14 | return false; | |
| 14580 | } | ||
| 14581 | 337635 | return true; | |
| 14582 | } | ||
| 14583 | |||
| 14584 |
3/4✓ Branch 0 taken 43498 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 360 times.
✓ Branch 3 taken 43138 times.
|
43498 | if (m_use_shared_space && !is_general_space) { |
| 14585 |
2/2✓ Branch 0 taken 231 times.
✓ Branch 1 taken 129 times.
|
360 | if (m_create_info->m_implicit_tablespace_autoextend_size_change && |
| 14586 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 230 times.
|
231 | m_create_info->m_implicit_tablespace_autoextend_size > 0) { |
| 14587 | /* AUTOEXTEND_SIZE is not allowed for system tablespace. */ | ||
| 14588 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 14589 | "InnoDB : AUTOEXTEND_SIZE is not accepted" | ||
| 14590 | " for system tablespace.", | ||
| 14591 | MYF(0)); | ||
| 14592 | 1 | return false; | |
| 14593 | } | ||
| 14594 | } | ||
| 14595 | |||
| 14596 | /* ALTER TABLE ... AUTOEXTEND_SIZE is not allowed if the tablespace is | ||
| 14597 | a general tablespace. */ | ||
| 14598 |
5/6✓ Branch 0 taken 43480 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 43135 times.
✓ Branch 3 taken 345 times.
✓ Branch 4 taken 43135 times.
✗ Branch 5 not taken.
|
43497 | if (!is_temp && is_general_space && m_use_shared_space) { |
| 14599 |
2/2✓ Branch 0 taken 21576 times.
✓ Branch 1 taken 21559 times.
|
43135 | if (m_create_info->m_implicit_tablespace_autoextend_size_change && |
| 14600 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 21570 times.
|
21576 | m_create_info->m_implicit_tablespace_autoextend_size > 0) { |
| 14601 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_INNODB_INCOMPATIBLE_WITH_TABLESPACE, MYF(0), |
| 14602 | "AUTOEXTEND_SIZE"); | ||
| 14603 | 6 | return false; | |
| 14604 | } | ||
| 14605 | } | ||
| 14606 | |||
| 14607 | /* Validate autoextend_size attribute value. */ | ||
| 14608 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 43489 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 43491 times.
|
43493 | if (m_create_info->m_implicit_tablespace_autoextend_size > 0 && |
| 14609 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | validate_autoextend_size_value( |
| 14610 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | m_create_info->m_implicit_tablespace_autoextend_size) != DB_SUCCESS) { |
| 14611 | ✗ | return false; | |
| 14612 | } | ||
| 14613 | |||
| 14614 | /* Name validation should be ensured from the SQL layer. */ | ||
| 14615 |
2/4✓ Branch 0 taken 43491 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43491 times.
|
43491 | ut_ad(0 == validate_tablespace_name(TS_CMD_NOT_DEFINED, |
| 14616 | m_create_info->tablespace)); | ||
| 14617 | |||
| 14618 | /* Look up the tablespace name in the fil_system. */ | ||
| 14619 |
1/2✓ Branch 0 taken 43491 times.
✗ Branch 1 not taken.
|
43491 | space_id_t space_id = fil_space_get_id_by_name(m_create_info->tablespace); |
| 14620 | |||
| 14621 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 43489 times.
|
43491 | if (space_id == SPACE_UNKNOWN) { |
| 14622 | 2 | my_printf_error(ER_TABLESPACE_MISSING, | |
| 14623 | "InnoDB: A general tablespace named" | ||
| 14624 | " `%s` cannot be found.", | ||
| 14625 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | MYF(0), m_create_info->tablespace); |
| 14626 | 2 | return false; | |
| 14627 | } | ||
| 14628 | |||
| 14629 |
3/4✓ Branch 0 taken 43489 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 43487 times.
|
43489 | if (fsp_is_undo_tablespace(space_id)) { |
| 14630 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 14631 | "InnoDB: An undo tablespace cannot contain tables.", | ||
| 14632 | MYF(0)); | ||
| 14633 | |||
| 14634 | 2 | return false; | |
| 14635 | } | ||
| 14636 | |||
| 14637 | /* Cannot add a second table to a file-per-table tablespace. */ | ||
| 14638 |
1/2✓ Branch 0 taken 43487 times.
✗ Branch 1 not taken.
|
43487 | uint32_t fsp_flags = fil_space_get_flags(space_id); |
| 14639 |
2/4✓ Branch 0 taken 43487 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43487 times.
|
43487 | if (fsp_is_file_per_table(space_id, fsp_flags)) { |
| 14640 | ✗ | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 14641 | "InnoDB: Tablespace `%s` is file-per-table so no" | ||
| 14642 | " other table can be added to it.", | ||
| 14643 | ✗ | MYF(0), m_create_info->tablespace); | |
| 14644 | ✗ | return false; | |
| 14645 | } | ||
| 14646 | |||
| 14647 |
1/2✓ Branch 0 taken 43487 times.
✗ Branch 1 not taken.
|
43487 | bool is_create_table = (thd_sql_command(m_thd) == SQLCOM_CREATE_TABLE); |
| 14648 | |||
| 14649 | /* If TABLESPACE=innodb_file_per_table this function is not called | ||
| 14650 | since tablespace_is_shared_space() will return false. Any other | ||
| 14651 | tablespace is incompatible with the DATA DIRECTORY phrase. | ||
| 14652 | On any ALTER TABLE that contains a DATA DIRECTORY, MySQL will issue | ||
| 14653 | a warning like "<DATA DIRECTORY> option ignored." The check below is | ||
| 14654 | needed for CREATE TABLE only. ALTER TABLE may be moving remote | ||
| 14655 | file-per-table table to a general tablespace, in which case the | ||
| 14656 | create_info->data_file_name is not null. */ | ||
| 14657 |
4/4✓ Branch 0 taken 20266 times.
✓ Branch 1 taken 23221 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20264 times.
|
43487 | if (is_create_table && m_create_info->data_file_name != nullptr && |
| 14658 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | *m_create_info->data_file_name != '\0') { |
| 14659 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 14660 | "InnoDB: DATA DIRECTORY cannot be used" | ||
| 14661 | " with a TABLESPACE assignment.", | ||
| 14662 | MYF(0)); | ||
| 14663 | 2 | return false; | |
| 14664 | } | ||
| 14665 | |||
| 14666 | /* Temp tables only belong in temp tablespaces. */ | ||
| 14667 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 43468 times.
|
43485 | if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { |
| 14668 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 13 times.
|
17 | if (!FSP_FLAGS_GET_TEMPORARY(fsp_flags)) { |
| 14669 | 4 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 14670 | "InnoDB: Tablespace `%s` cannot contain" | ||
| 14671 | " TEMPORARY tables.", | ||
| 14672 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | MYF(0), m_create_info->tablespace); |
| 14673 | 4 | return false; | |
| 14674 | } | ||
| 14675 | |||
| 14676 | /* Restrict Compressed Temporary General tablespaces. */ | ||
| 14677 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (m_create_info->key_block_size || |
| 14678 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
|
13 | m_create_info->row_type == ROW_TYPE_COMPRESSED) { |
| 14679 | 1 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 14680 | "InnoDB: Temporary tablespace `%s` cannot" | ||
| 14681 | " contain COMPRESSED tables.", | ||
| 14682 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | MYF(0), m_create_info->tablespace); |
| 14683 | 1 | return false; | |
| 14684 | } | ||
| 14685 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 43464 times.
|
43468 | } else if (FSP_FLAGS_GET_TEMPORARY(fsp_flags)) { |
| 14686 | 4 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 14687 | "InnoDB: Tablespace `%s` can only contain" | ||
| 14688 | " TEMPORARY tables.", | ||
| 14689 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | MYF(0), m_create_info->tablespace); |
| 14690 | 4 | return false; | |
| 14691 | } | ||
| 14692 | |||
| 14693 | /* Make sure the physical page size of the table matches the | ||
| 14694 | file block size of the tablespace. */ | ||
| 14695 | ulint block_size_needed; | ||
| 14696 | bool table_is_compressed; | ||
| 14697 |
2/2✓ Branch 0 taken 119 times.
✓ Branch 1 taken 43357 times.
|
43476 | if (m_create_info->key_block_size) { |
| 14698 | 119 | block_size_needed = m_create_info->key_block_size * 1024; | |
| 14699 | 119 | table_is_compressed = true; | |
| 14700 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 43349 times.
|
43357 | } else if (m_create_info->row_type == ROW_TYPE_COMPRESSED) { |
| 14701 | 8 | block_size_needed = | |
| 14702 | 8 | std::min(UNIV_PAGE_SIZE / 2, static_cast<ulint>(UNIV_ZIP_SIZE_MAX)); | |
| 14703 | 8 | table_is_compressed = true; | |
| 14704 | } else { | ||
| 14705 | 43349 | block_size_needed = UNIV_PAGE_SIZE; | |
| 14706 | 43349 | table_is_compressed = false; | |
| 14707 | } | ||
| 14708 | |||
| 14709 |
1/2✓ Branch 0 taken 43476 times.
✗ Branch 1 not taken.
|
43476 | const page_size_t page_size(fsp_flags); |
| 14710 | |||
| 14711 | /* The compression code needs some work in order for a general | ||
| 14712 | tablespace to contain both compressed and non-compressed tables | ||
| 14713 | together in the same tablespace. The problem seems to be that | ||
| 14714 | each page is either compressed or not based on the fsp flags, | ||
| 14715 | which is shared by all tables in that general tablespace. */ | ||
| 14716 |
7/8✓ Branch 0 taken 127 times.
✓ Branch 1 taken 43349 times.
✓ Branch 2 taken 127 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 98 times.
✓ Branch 6 taken 29 times.
✓ Branch 7 taken 43447 times.
|
43476 | if (table_is_compressed && page_size.physical() == UNIV_PAGE_SIZE) { |
| 14717 | 29 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 14718 | "InnoDB: Tablespace `%s` cannot contain a" | ||
| 14719 | " COMPRESSED table", | ||
| 14720 |
1/2✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
|
29 | MYF(0), m_create_info->tablespace); |
| 14721 | 29 | return false; | |
| 14722 | } | ||
| 14723 | |||
| 14724 |
3/4✓ Branch 0 taken 43447 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 43371 times.
|
43447 | if (block_size_needed != page_size.physical()) { |
| 14725 |
1/2✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
|
76 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 14726 | "InnoDB: Tablespace `%s` uses block size %zu" | ||
| 14727 | " and cannot contain a table with physical" | ||
| 14728 | " page size " ULINTPF, | ||
| 14729 |
1/2✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
|
76 | MYF(0), m_create_info->tablespace, page_size.physical(), |
| 14730 | block_size_needed); | ||
| 14731 | 76 | return false; | |
| 14732 | } | ||
| 14733 | |||
| 14734 | 43371 | return true; | |
| 14735 | } | ||
| 14736 | |||
| 14737 | /** Validate the COPMRESSION option. | ||
| 14738 | @return true if valid, false if not. */ | ||
| 14739 | 761286 | bool create_table_info_t::create_option_compression_is_valid() { | |
| 14740 | dberr_t err; | ||
| 14741 | 761286 | Compression compression; | |
| 14742 | |||
| 14743 |
2/2✓ Branch 0 taken 760984 times.
✓ Branch 1 taken 303 times.
|
761287 | if (m_create_info->compress.length == 0) { |
| 14744 | 760984 | return (true); | |
| 14745 | } | ||
| 14746 | |||
| 14747 |
1/2✓ Branch 0 taken 303 times.
✗ Branch 1 not taken.
|
303 | err = Compression::check(m_create_info->compress.str, &compression); |
| 14748 | |||
| 14749 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 297 times.
|
303 | if (err == DB_UNSUPPORTED) { |
| 14750 | 6 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 14751 | ER_UNSUPPORTED_EXTENSION, | ||
| 14752 | "InnoDB: Unsupported compression algorithm '%s'", | ||
| 14753 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | m_create_info->compress.str); |
| 14754 | 6 | return (false); | |
| 14755 | } | ||
| 14756 | |||
| 14757 | /* Allow Compression=NONE on any tablespace or row format. */ | ||
| 14758 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 225 times.
|
297 | if (compression.m_type == Compression::NONE) { |
| 14759 | 72 | return (true); | |
| 14760 | } | ||
| 14761 | |||
| 14762 | static char intro[] = "InnoDB: Page Compression is not supported"; | ||
| 14763 | |||
| 14764 |
2/2✓ Branch 0 taken 221 times.
✓ Branch 1 taken 4 times.
|
225 | if (m_create_info->key_block_size != 0 || |
| 14765 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 215 times.
|
221 | m_create_info->row_type == ROW_TYPE_COMPRESSED) { |
| 14766 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, |
| 14767 | ER_UNSUPPORTED_EXTENSION, | ||
| 14768 | "%s with row_format=compressed or" | ||
| 14769 | " key_block_size > 0", | ||
| 14770 | intro); | ||
| 14771 | 10 | return (false); | |
| 14772 | } | ||
| 14773 | |||
| 14774 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 210 times.
|
215 | if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { |
| 14775 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 14776 | "%s for temporary tables", intro); | ||
| 14777 | 5 | return (false); | |
| 14778 | } | ||
| 14779 | |||
| 14780 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 204 times.
|
210 | if (tablespace_is_general_space(m_create_info)) { |
| 14781 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 14782 | "%s for shared general tablespaces", intro); | ||
| 14783 | 6 | return (false); | |
| 14784 | } | ||
| 14785 | |||
| 14786 | /* The only non-file-per-table tablespace left is the system space. */ | ||
| 14787 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 197 times.
|
204 | if (!m_use_file_per_table) { |
| 14788 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 14789 | "%s for the system tablespace", intro); | ||
| 14790 | 7 | return (false); | |
| 14791 | } | ||
| 14792 | |||
| 14793 | 197 | return (true); | |
| 14794 | } | ||
| 14795 | |||
| 14796 | /** Validate ENCRYPTION option. | ||
| 14797 | @return true if valid, false if not. */ | ||
| 14798 | 381006 | bool create_table_info_t::create_option_encryption_is_valid() const { | |
| 14799 |
2/2✓ Branch 0 taken 69271 times.
✓ Branch 1 taken 311735 times.
|
381006 | if (m_create_info->encrypt_type.length > 0) { |
| 14800 | 69271 | dberr_t err = Encryption::validate(m_create_info->encrypt_type.str); | |
| 14801 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69272 times.
|
69272 | if (err == DB_UNSUPPORTED) { |
| 14802 | ✗ | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); | |
| 14803 | ✗ | return (false); | |
| 14804 | } | ||
| 14805 | } | ||
| 14806 | |||
| 14807 | bool table_is_keyring = | ||
| 14808 | 381007 | Encryption::is_keyring(m_create_info->encrypt_type.str); | |
| 14809 | |||
| 14810 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 381007 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
381007 | if (table_is_keyring && !m_allow_file_per_table) { |
| 14811 | ✗ | my_printf_error(ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION, | |
| 14812 | "InnoDB: KEYRING requires innodb_file_per_table.", MYF(0)); | ||
| 14813 | ✗ | return (false); | |
| 14814 | } | ||
| 14815 | |||
| 14816 |
2/2✓ Branch 0 taken 2780 times.
✓ Branch 1 taken 378226 times.
|
381006 | if (!table_is_keyring && |
| 14817 |
3/6✓ Branch 0 taken 381007 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2781 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 381007 times.
|
762014 | Encryption::is_master_key_encryption(m_create_info->encrypt_type.str) && |
| 14818 | 2780 | Encryption::is_online_encryption_on()) { | |
| 14819 | ✗ | my_printf_error(ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION, | |
| 14820 | "InnoDB: ENCRYPTED='Y' not supported for table because " | ||
| 14821 | "online encryption to KEYRING is turned ON.", | ||
| 14822 | MYF(0)); | ||
| 14823 | ✗ | return (false); | |
| 14824 | } | ||
| 14825 | |||
| 14826 | /* Currently we do not support keyring encryption for | ||
| 14827 | spatial indexes thus do not allow creating table with forced | ||
| 14828 | encryption */ | ||
| 14829 | |||
| 14830 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 381002 times.
|
381007 | if (Encryption::should_be_keyring_encrypted( |
| 14831 | 381007 | m_create_info->explicit_encryption, | |
| 14832 | 381007 | m_create_info->encrypt_type.str)) { | |
| 14833 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
|
6 | for (ulint i = 0; i < m_form->s->keys; i++) { |
| 14834 | 1 | const KEY *key = m_form->key_info + i; | |
| 14835 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (key->flags & HA_SPATIAL) { |
| 14836 | ✗ | my_printf_error( | |
| 14837 | ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION, | ||
| 14838 | "InnoDB: ENCRYPTED='KEYRING' not supported for table because " | ||
| 14839 | "it contains spatial index.", | ||
| 14840 | MYF(0)); | ||
| 14841 | ✗ | return (false); | |
| 14842 | } | ||
| 14843 | } | ||
| 14844 | } | ||
| 14845 | |||
| 14846 | const bool table_is_encrypted = | ||
| 14847 | 381007 | !Encryption::is_none(m_create_info->encrypt_type.str); | |
| 14848 | |||
| 14849 | ulint space_id; | ||
| 14850 |
2/2✓ Branch 0 taken 43371 times.
✓ Branch 1 taken 337636 times.
|
381007 | if (m_use_shared_space) { |
| 14851 | 43371 | space_id = fil_space_get_id_by_name(m_create_info->tablespace); | |
| 14852 |
2/2✓ Branch 0 taken 153535 times.
✓ Branch 1 taken 184101 times.
|
337636 | } else if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { |
| 14853 | 153535 | space_id = srv_tmp_space.space_id(); | |
| 14854 |
2/2✓ Branch 0 taken 4535 times.
✓ Branch 1 taken 179566 times.
|
184101 | } else if (!m_use_file_per_table) { |
| 14855 | 4535 | space_id = TRX_SYS_SPACE; | |
| 14856 | } else { | ||
| 14857 | 179566 | return (true); | |
| 14858 | } | ||
| 14859 | |||
| 14860 | 201441 | fil_space_t *space = fil_space_get(space_id); | |
| 14861 | 201441 | const auto fsp_flags = space->flags; | |
| 14862 | |||
| 14863 | 201441 | const bool tablespace_is_encrypted = FSP_FLAGS_GET_ENCRYPTION(fsp_flags); | |
| 14864 | 201441 | const char *const tablespace_name = | |
| 14865 |
2/2✓ Branch 0 taken 46459 times.
✓ Branch 1 taken 154982 times.
|
201441 | m_create_info->tablespace ? m_create_info->tablespace : space->name; |
| 14866 | |||
| 14867 |
3/4✓ Branch 0 taken 1565 times.
✓ Branch 1 taken 199876 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1565 times.
|
201441 | if (table_is_encrypted && !tablespace_is_encrypted) { |
| 14868 | ✗ | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 14869 | "InnoDB: Tablespace `%s` cannot contain an" | ||
| 14870 | " ENCRYPTED table.", | ||
| 14871 | MYF(0), tablespace_name); | ||
| 14872 | ✗ | return (false); | |
| 14873 | } | ||
| 14874 | |||
| 14875 | 201441 | return (true); | |
| 14876 | } | ||
| 14877 | |||
| 14878 | /** Validate the create options. Check that the options KEY_BLOCK_SIZE, | ||
| 14879 | ROW_FORMAT, DATA DIRECTORY, TEMPORARY & TABLESPACE are compatible with | ||
| 14880 | each other and other settings. These CREATE OPTIONS are not validated | ||
| 14881 | here unless innodb_strict_mode is on. With strict mode, this function | ||
| 14882 | will report each problem it finds using a custom message with error | ||
| 14883 | code ER_ILLEGAL_HA_CREATE_OPTION, not its built-in message. | ||
| 14884 | @return NULL if valid, string name of bad option if not. */ | ||
| 14885 | 381168 | const char *create_table_info_t::create_options_are_invalid() { | |
| 14886 | 381168 | bool has_key_block_size = (m_create_info->key_block_size != 0); | |
| 14887 | 381168 | bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 14888 | |||
| 14889 | 381168 | const char *ret = nullptr; | |
| 14890 | 381168 | enum row_type row_format = m_create_info->row_type; | |
| 14891 | |||
| 14892 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 381169 times.
|
381168 | ut_ad(m_thd != nullptr); |
| 14893 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 381169 times.
|
381169 | ut_ad(m_create_info != nullptr); |
| 14894 | |||
| 14895 | /* The TABLESPACE designation on a CREATE TABLE is not subject to | ||
| 14896 | non-strict-mode. If it is incorrect or is incompatible with other | ||
| 14897 | options, then we will return an error. Make sure the tablespace exists | ||
| 14898 | and is compatible with this table */ | ||
| 14899 |
2/2✓ Branch 0 taken 162 times.
✓ Branch 1 taken 381006 times.
|
381169 | if (!create_option_tablespace_is_valid()) { |
| 14900 | 162 | return ("TABLESPACE"); | |
| 14901 | } | ||
| 14902 | |||
| 14903 | /* Validate encryption parameter even if strict_mode is OFF. */ | ||
| 14904 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 381007 times.
|
381006 | if (!create_option_encryption_is_valid()) return ("ENCRYPTION"); |
| 14905 | |||
| 14906 | /* If innodb_strict_mode is not set don't do any more validation. | ||
| 14907 | Also, if this table is being put into a shared general tablespace | ||
| 14908 | we ALWAYS act like strict mode is ON. | ||
| 14909 | Or if caller explicitly asks for skipping strict mode check (if | ||
| 14910 | tablespace is not a shared general tablespace), then skip */ | ||
| 14911 |
8/8✓ Branch 0 taken 337636 times.
✓ Branch 1 taken 43371 times.
✓ Branch 2 taken 336604 times.
✓ Branch 3 taken 1032 times.
✓ Branch 4 taken 14665 times.
✓ Branch 5 taken 321939 times.
✓ Branch 6 taken 15697 times.
✓ Branch 7 taken 365310 times.
|
381007 | if (!m_use_shared_space && (!(THDVAR(m_thd, strict_mode)) || skip_strict())) { |
| 14912 | 15697 | return (nullptr); | |
| 14913 | } | ||
| 14914 | |||
| 14915 | /* Check if a non-zero KEY_BLOCK_SIZE was specified. */ | ||
| 14916 |
2/2✓ Branch 0 taken 299 times.
✓ Branch 1 taken 365011 times.
|
365310 | if (has_key_block_size) { |
| 14917 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 289 times.
|
299 | if (is_temp) { |
| 14918 | 10 | my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, MYF(0)); | |
| 14919 | 10 | return ("KEY_BLOCK_SIZE"); | |
| 14920 | } | ||
| 14921 | |||
| 14922 |
2/2✓ Branch 0 taken 280 times.
✓ Branch 1 taken 9 times.
|
289 | switch (m_create_info->key_block_size) { |
| 14923 | ulint kbs_max; | ||
| 14924 | 280 | case 1: | |
| 14925 | case 2: | ||
| 14926 | case 4: | ||
| 14927 | case 8: | ||
| 14928 | case 16: | ||
| 14929 | /* The maximum KEY_BLOCK_SIZE (KBS) is | ||
| 14930 | UNIV_PAGE_SIZE_MAX. But if UNIV_PAGE_SIZE is | ||
| 14931 | smaller than UNIV_PAGE_SIZE_MAX, the maximum | ||
| 14932 | KBS is also smaller. */ | ||
| 14933 | 560 | kbs_max = std::min(1 << (UNIV_PAGE_SSIZE_MAX - 1), | |
| 14934 | 280 | 1 << (PAGE_ZIP_SSIZE_MAX - 1)); | |
| 14935 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
|
280 | if (m_create_info->key_block_size > kbs_max) { |
| 14936 | ✗ | push_warning_printf( | |
| 14937 | m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14938 | "InnoDB: KEY_BLOCK_SIZE=%" PRIu32 " cannot be larger than %ld.", | ||
| 14939 | ✗ | m_create_info->key_block_size, kbs_max); | |
| 14940 | ✗ | ret = "KEY_BLOCK_SIZE"; | |
| 14941 | } | ||
| 14942 | |||
| 14943 | /* The following checks do not appy to shared tablespaces */ | ||
| 14944 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 248 times.
|
280 | if (m_use_shared_space) { |
| 14945 | 32 | break; | |
| 14946 | } | ||
| 14947 | |||
| 14948 | /* Valid KEY_BLOCK_SIZE, check its dependencies. */ | ||
| 14949 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 241 times.
|
248 | if (!m_allow_file_per_table) { |
| 14950 | 7 | push_warning(m_thd, Sql_condition::SL_WARNING, | |
| 14951 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14952 | "InnoDB: KEY_BLOCK_SIZE requires" | ||
| 14953 | " innodb_file_per_table."); | ||
| 14954 | 7 | ret = "KEY_BLOCK_SIZE"; | |
| 14955 | } | ||
| 14956 | 248 | break; | |
| 14957 | 9 | default: | |
| 14958 | 9 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 14959 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14960 | "InnoDB: invalid KEY_BLOCK_SIZE = %" PRIu32 | ||
| 14961 | ". Valid values are [1, 2, 4, 8, 16]", | ||
| 14962 | 9 | m_create_info->key_block_size); | |
| 14963 | 9 | ret = "KEY_BLOCK_SIZE"; | |
| 14964 | 9 | break; | |
| 14965 | } | ||
| 14966 | } | ||
| 14967 | |||
| 14968 | /* Check for a valid InnoDB ROW_FORMAT specifier and | ||
| 14969 | other incompatibilities. */ | ||
| 14970 |
5/5✓ Branch 0 taken 768 times.
✓ Branch 1 taken 39594 times.
✓ Branch 2 taken 324931 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 times.
|
365300 | switch (row_format) { |
| 14971 | 768 | case ROW_TYPE_COMPRESSED: | |
| 14972 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 763 times.
|
768 | if (is_temp) { |
| 14973 | 5 | my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, MYF(0)); | |
| 14974 | 5 | return ("ROW_FORMAT"); | |
| 14975 | } | ||
| 14976 |
4/4✓ Branch 0 taken 742 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 740 times.
|
763 | if (!m_use_shared_space && !m_allow_file_per_table) { |
| 14977 | 2 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 14978 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14979 | "InnoDB: %s requires innodb_file_per_table.", | ||
| 14980 | get_row_format_name(row_format)); | ||
| 14981 | 2 | ret = "ROW_FORMAT"; | |
| 14982 | } | ||
| 14983 | 763 | break; | |
| 14984 | 39594 | case ROW_TYPE_DYNAMIC: | |
| 14985 | case ROW_TYPE_COMPACT: | ||
| 14986 | case ROW_TYPE_REDUNDANT: | ||
| 14987 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 39572 times.
|
39594 | if (has_key_block_size) { |
| 14988 | 22 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 14989 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14990 | "InnoDB: cannot specify %s" | ||
| 14991 | " with KEY_BLOCK_SIZE.", | ||
| 14992 | get_row_format_name(row_format)); | ||
| 14993 | 22 | ret = "KEY_BLOCK_SIZE"; | |
| 14994 | } | ||
| 14995 | 39594 | break; | |
| 14996 | 324931 | case ROW_TYPE_DEFAULT: | |
| 14997 | 324931 | break; | |
| 14998 | 6 | case ROW_TYPE_FIXED: | |
| 14999 | case ROW_TYPE_PAGED: | ||
| 15000 | case ROW_TYPE_NOT_USED: | ||
| 15001 | 6 | push_warning(m_thd, Sql_condition::SL_WARNING, | |
| 15002 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15003 | "InnoDB: invalid ROW_FORMAT specifier."); | ||
| 15004 | 6 | ret = "ROW_TYPE"; | |
| 15005 | 6 | break; | |
| 15006 | } | ||
| 15007 | |||
| 15008 | 754053 | if (m_create_info->data_file_name != nullptr && | |
| 15009 |
8/8✓ Branch 0 taken 23463 times.
✓ Branch 1 taken 341832 times.
✓ Branch 2 taken 485 times.
✓ Branch 3 taken 22978 times.
✓ Branch 4 taken 410 times.
✓ Branch 5 taken 75 times.
✓ Branch 6 taken 25 times.
✓ Branch 7 taken 365270 times.
|
365705 | *m_create_info->data_file_name != '\0' && m_table_name != nullptr && |
| 15010 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 385 times.
|
410 | !create_option_data_directory_is_valid()) { |
| 15011 | 25 | ret = "DATA DIRECTORY"; | |
| 15012 | } | ||
| 15013 | |||
| 15014 | /* Do not allow INDEX_DIRECTORY */ | ||
| 15015 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 365291 times.
|
365295 | if (m_create_info->index_file_name) { |
| 15016 | 4 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 15017 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15018 | "InnoDB: INDEX DIRECTORY is not supported"); | ||
| 15019 | 4 | ret = "INDEX DIRECTORY"; | |
| 15020 | } | ||
| 15021 | |||
| 15022 | /* Don't support compressed table when page size > 16k. */ | ||
| 15023 |
4/4✓ Branch 0 taken 365005 times.
✓ Branch 1 taken 290 times.
✓ Branch 2 taken 581 times.
✓ Branch 3 taken 364424 times.
|
365295 | if ((has_key_block_size || row_format == ROW_TYPE_COMPRESSED) && |
| 15024 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 871 times.
|
871 | UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) { |
| 15025 | ✗ | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, | |
| 15026 | "InnoDB: Cannot create a COMPRESSED table" | ||
| 15027 | " when innodb_page_size > 16k."); | ||
| 15028 | |||
| 15029 | ✗ | if (has_key_block_size) { | |
| 15030 | ✗ | ret = "KEY_BLOCK_SIZE"; | |
| 15031 | } else { | ||
| 15032 | ✗ | ret = "ROW_TYPE"; | |
| 15033 | } | ||
| 15034 | } | ||
| 15035 | |||
| 15036 | /* Validate the page compression parameter. */ | ||
| 15037 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 365270 times.
|
365295 | if (!create_option_compression_is_valid()) { |
| 15038 | 24 | return ("COMPRESSION"); | |
| 15039 | } | ||
| 15040 | |||
| 15041 | /* Check the encryption option. */ | ||
| 15042 |
4/4✓ Branch 0 taken 365202 times.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 54375 times.
✓ Branch 3 taken 310827 times.
|
365270 | if (ret == nullptr && m_create_info->encrypt_type.str != nullptr) { |
| 15043 | dberr_t err; | ||
| 15044 | |||
| 15045 | 54375 | err = Encryption::validate(m_create_info->encrypt_type.str); | |
| 15046 | |||
| 15047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54376 times.
|
54376 | if (err == DB_UNSUPPORTED) { |
| 15048 | ✗ | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); | |
| 15049 | ✗ | ret = "ENCRYPTION"; | |
| 15050 | } | ||
| 15051 | } | ||
| 15052 | |||
| 15053 | 365271 | return (ret); | |
| 15054 | } | ||
| 15055 | |||
| 15056 | 224965 | void ha_innobase::adjust_encryption_key_id(HA_CREATE_INFO *create_info, | |
| 15057 | dd::Properties *options) noexcept { | ||
| 15058 |
2/2✓ Branch 0 taken 224963 times.
✓ Branch 1 taken 2 times.
|
224965 | if (false == create_info->was_encryption_key_id_set) { |
| 15059 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 224963 times.
|
224963 | if (Encryption::should_be_keyring_encrypted( |
| 15060 | 224963 | create_info->explicit_encryption, create_info->encrypt_type.str)) { | |
| 15061 | ✗ | create_info->encryption_key_id = | |
| 15062 | ✗ | THDVAR(current_thd, default_encryption_key_id); | |
| 15063 | } | ||
| 15064 | } else { | ||
| 15065 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (options && (create_info->tablespace == nullptr || |
| 15066 | ✗ | strcmp(create_info->tablespace, | |
| 15067 | dict_sys_t::s_file_per_table_name) == 0)) { | ||
| 15068 | 2 | options->set("encryption_key_id", create_info->encryption_key_id); | |
| 15069 | } | ||
| 15070 | |||
| 15071 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
4 | if (Encryption::is_master_key_encryption(create_info->encrypt_type.str) || |
| 15072 | 2 | Encryption::none_explicitly_specified(create_info->explicit_encryption, | |
| 15073 | 2 | create_info->encrypt_type.str)) { | |
| 15074 | // if it is encrypted table with Master key encryption or marked as not to | ||
| 15075 | // be encrypted and alter table does not have ENCRYPTION_KEY_ID - mark | ||
| 15076 | // encryption key id as not set. | ||
| 15077 | |||
| 15078 | ✗ | push_warning_printf( | |
| 15079 | ✗ | current_thd, Sql_condition::SL_WARNING, HA_WRONG_CREATE_OPTION, | |
| 15080 | ✗ | Encryption::none_explicitly_specified( | |
| 15081 | ✗ | create_info->explicit_encryption, create_info->encrypt_type.str) | |
| 15082 | ? "InnoDB: Ignored ENCRYPTION_KEY_ID %u when " | ||
| 15083 | "encryption is disabled." | ||
| 15084 | : "InnoDB: Ignored ENCRYPTION_KEY_ID %u when " | ||
| 15085 | "Master Key encryption is enabled.", | ||
| 15086 | create_info->encryption_key_id); | ||
| 15087 | ✗ | create_info->encryption_key_id = FIL_DEFAULT_ENCRYPTION_KEY; | |
| 15088 | ✗ | create_info->was_encryption_key_id_set = false; | |
| 15089 | ✗ | options->remove("encryption_key_id"); | |
| 15090 | } | ||
| 15091 | } | ||
| 15092 | 224965 | } | |
| 15093 | |||
| 15094 | /** Adjust encryption options. | ||
| 15095 | @param[in,out] create_info Additional create information. | ||
| 15096 | @param[in,out] table_def dd::Table object to be modified.*/ | ||
| 15097 | 318377 | void ha_innobase::adjust_encryption_options(HA_CREATE_INFO *create_info, | |
| 15098 | dd::Table *table_def) noexcept { | ||
| 15099 | 318377 | bool is_intrinsic = | |
| 15100 | 318377 | (create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE) != 0; | |
| 15101 | |||
| 15102 |
2/2✓ Branch 0 taken 110977 times.
✓ Branch 1 taken 207400 times.
|
318377 | if (is_intrinsic) { |
| 15103 | 110977 | return; | |
| 15104 | } | ||
| 15105 | |||
| 15106 | #ifdef UNIV_DEBUG | ||
| 15107 | // check that create_info->explicit_encryption is in sync with | ||
| 15108 | // DD's explicit_encryption | ||
| 15109 |
2/2✓ Branch 0 taken 13527 times.
✓ Branch 1 taken 193873 times.
|
207400 | if (create_info->explicit_encryption) { |
| 15110 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13527 times.
|
13527 | ut_ad(table_def->options().exists("explicit_encryption")); |
| 15111 | 13527 | bool explicit_encryption{false}; | |
| 15112 | 13527 | table_def->options().get("explicit_encryption", &explicit_encryption); | |
| 15113 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13527 times.
|
13527 | ut_ad(explicit_encryption); |
| 15114 | } | ||
| 15115 | #endif /* UNIV_DEBUG */ | ||
| 15116 | |||
| 15117 | 207400 | bool is_tmp = (create_info->options & HA_LEX_CREATE_TMP_TABLE) != 0; | |
| 15118 | |||
| 15119 |
2/2✓ Branch 0 taken 42539 times.
✓ Branch 1 taken 164861 times.
|
207400 | if (is_tmp) { |
| 15120 | 42539 | return; | |
| 15121 | } | ||
| 15122 | |||
| 15123 |
1/2✓ Branch 0 taken 164861 times.
✗ Branch 1 not taken.
|
329722 | adjust_encryption_key_id(create_info, |
| 15124 | 164861 | table_def ? &(table_def->options()) : nullptr); | |
| 15125 | } | ||
| 15126 | |||
| 15127 | /** Update create_info. Used in SHOW CREATE TABLE et al. */ | ||
| 15128 | |||
| 15129 | 124154 | void ha_innobase::update_create_info( | |
| 15130 | HA_CREATE_INFO *create_info) /*!< in/out: create info */ | ||
| 15131 | { | ||
| 15132 |
2/2✓ Branch 0 taken 123961 times.
✓ Branch 1 taken 193 times.
|
124154 | if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) { |
| 15133 | 123961 | info(HA_STATUS_AUTO); | |
| 15134 | 123961 | create_info->auto_increment_value = stats.auto_increment_value; | |
| 15135 | } | ||
| 15136 | |||
| 15137 | /* Update the DATA DIRECTORY name. */ | ||
| 15138 | 124154 | dd_get_and_save_data_dir_path<dd::Table>(m_prebuilt->table, nullptr, false); | |
| 15139 | |||
| 15140 |
2/2✓ Branch 0 taken 172 times.
✓ Branch 1 taken 123982 times.
|
124154 | if (m_prebuilt->table->data_dir_path != nullptr) { |
| 15141 | 172 | create_info->data_file_name = m_prebuilt->table->data_dir_path; | |
| 15142 | } | ||
| 15143 | |||
| 15144 | /* Update the TABLESPACE name from the Data Dictionary. */ | ||
| 15145 | 124154 | dict_get_and_save_space_name(m_prebuilt->table); | |
| 15146 | |||
| 15147 | /* Put this tablespace name into the create_info structure so that | ||
| 15148 | SHOW CREATE TABLE will display TABLESPACE=name. This also affects | ||
| 15149 | an ALTER TABLE which must know the current TABLESPACE so that the | ||
| 15150 | table will stay there. */ | ||
| 15151 |
4/4✓ Branch 0 taken 38046 times.
✓ Branch 1 taken 86108 times.
✓ Branch 2 taken 2244 times.
✓ Branch 3 taken 121910 times.
|
162200 | if (m_prebuilt->table->tablespace != nullptr && |
| 15152 |
2/2✓ Branch 0 taken 2244 times.
✓ Branch 1 taken 35802 times.
|
38046 | create_info->tablespace == nullptr) { |
| 15153 | 2244 | create_info->tablespace = m_prebuilt->table->tablespace; | |
| 15154 | } | ||
| 15155 | 124154 | } | |
| 15156 | |||
| 15157 | /** Initialize the table FTS stopword list | ||
| 15158 | @return true if success */ | ||
| 15159 | 649 | bool innobase_fts_load_stopword( | |
| 15160 | dict_table_t *table, /*!< in: Table has the FTS */ | ||
| 15161 | trx_t *trx, /*!< in: transaction */ | ||
| 15162 | THD *thd) /*!< in: current thread */ | ||
| 15163 | { | ||
| 15164 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
|
649 | ut_ad(!dict_sys_mutex_own()); |
| 15165 | |||
| 15166 | 1947 | return (fts_load_stopword(table, trx, innobase_server_stopword_table, | |
| 15167 | 649 | THDVAR(thd, ft_user_stopword_table), | |
| 15168 | 1298 | THDVAR(thd, ft_enable_stopword), false)); | |
| 15169 | } | ||
| 15170 | |||
| 15171 | 9707 | static bool innobase_ddse_dict_init( | |
| 15172 | dict_init_mode_t dict_init_mode, uint, List<const dd::Object_table> *tables, | ||
| 15173 | List<const Plugin_tablespace> *tablespaces) { | ||
| 15174 |
1/2✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
|
9707 | DBUG_TRACE; |
| 15175 | |||
| 15176 |
8/16✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9707 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9707 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9707 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9707 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9707 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9707 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9707 times.
✗ Branch 15 not taken.
|
9707 | LogErr(SYSTEM_LEVEL, ER_IB_MSG_INNODB_START_INITIALIZE); |
| 15177 | |||
| 15178 |
2/4✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9707 times.
✗ Branch 3 not taken.
|
9707 | assert(tables && tables->is_empty()); |
| 15179 |
2/4✓ Branch 0 taken 9707 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9707 times.
✗ Branch 3 not taken.
|
9707 | assert(tablespaces && tablespaces->is_empty()); |
| 15180 | |||
| 15181 |
2/2✓ Branch 0 taken 9631 times.
✓ Branch 1 taken 76 times.
|
9707 | if (dblwr::is_enabled()) { |
| 15182 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9623 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
9631 | if (innobase_doublewrite_dir != nullptr && *innobase_doublewrite_dir != 0) { |
| 15183 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | dblwr::dir.assign(innobase_doublewrite_dir); |
| 15184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | switch (dblwr::dir.front()) { |
| 15185 | ✗ | case '#': | |
| 15186 | case '.': | ||
| 15187 | ✗ | break; | |
| 15188 | 8 | default: | |
| 15189 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (!Fil_path::is_absolute_path(dblwr::dir)) { |
| 15190 | ✗ | dblwr::dir.insert(0, "#"); | |
| 15191 | } | ||
| 15192 | } | ||
| 15193 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
16 | ib::info(ER_IB_MSG_DBLWR_1325) |
| 15194 |
3/6✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
16 | << "Using " << dblwr::dir << " as doublewrite directory"; |
| 15195 | } else { | ||
| 15196 |
1/2✓ Branch 0 taken 9623 times.
✗ Branch 1 not taken.
|
9623 | dblwr::dir.assign("."); |
| 15197 | } | ||
| 15198 |
2/4✓ Branch 0 taken 9631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9631 times.
✗ Branch 3 not taken.
|
9631 | ib::info(ER_IB_MSG_DBLWR_1304) << "Atomic write enabled"; |
| 15199 | } else { | ||
| 15200 |
2/4✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✗ Branch 3 not taken.
|
76 | ib::info(ER_IB_MSG_DBLWR_1305) << "Atomic write disabled"; |
| 15201 | } | ||
| 15202 | |||
| 15203 | 9707 | bool is_dd_encrypted{false}; | |
| 15204 | |||
| 15205 |
3/4✓ Branch 0 taken 9706 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 9622 times.
|
9707 | if (innobase_init_files(dict_init_mode, tablespaces, is_dd_encrypted)) { |
| 15206 | 84 | return true; | |
| 15207 | } | ||
| 15208 | |||
| 15209 | /* Instantiate table defs only if we are successful so far. */ | ||
| 15210 | dd::Object_table *innodb_dynamic_metadata = | ||
| 15211 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | dd::Object_table::create_object_table(); |
| 15212 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | innodb_dynamic_metadata->set_hidden(true); |
| 15213 | dd::Object_table_definition *def = | ||
| 15214 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | innodb_dynamic_metadata->target_table_definition(); |
| 15215 |
2/4✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
|
9622 | def->set_table_name("innodb_dynamic_metadata"); |
| 15216 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(0, "table_id", "table_id BIGINT UNSIGNED NOT NULL"); |
| 15217 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(1, "version", "version BIGINT UNSIGNED NOT NULL"); |
| 15218 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(2, "metadata", "metadata BLOB NOT NULL"); |
| 15219 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_index(0, "index_pk", "PRIMARY KEY (table_id)"); |
| 15220 | /* Options and tablespace are set at the SQL layer. */ | ||
| 15221 | |||
| 15222 | /* Changing these values would change the specification of innodb statistics | ||
| 15223 | tables. */ | ||
| 15224 | static constexpr size_t DB_NAME_FIELD_SIZE = 64; | ||
| 15225 | static constexpr size_t TABLE_NAME_FIELD_SIZE = 199; | ||
| 15226 | |||
| 15227 | static_assert(DB_NAME_FIELD_SIZE == dict_name::MAX_DB_CHAR_LEN, | ||
| 15228 | "dict_name::MAX_DB_CHAR_LEN mismatch with db column"); | ||
| 15229 | |||
| 15230 | static_assert(TABLE_NAME_FIELD_SIZE == dict_name::MAX_TABLE_CHAR_LEN, | ||
| 15231 | "dict_name::MAX_TABLE_CHAR_LEN mismatch with table column"); | ||
| 15232 | |||
| 15233 | /* Set length for database name field. */ | ||
| 15234 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
19244 | std::ostringstream db_name_field; |
| 15235 |
2/4✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
|
9622 | db_name_field << "database_name VARCHAR(" << DB_NAME_FIELD_SIZE |
| 15236 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | << ") NOT NULL"; |
| 15237 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
19244 | std::string db_field = db_name_field.str(); |
| 15238 | |||
| 15239 | /* Set length for table name field. */ | ||
| 15240 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
19244 | std::ostringstream table_name_field; |
| 15241 |
2/4✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
|
9622 | table_name_field << "table_name VARCHAR(" << TABLE_NAME_FIELD_SIZE |
| 15242 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | << ") NOT NULL"; |
| 15243 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | std::string table_field = table_name_field.str(); |
| 15244 | |||
| 15245 | dd::Object_table *innodb_table_stats = | ||
| 15246 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | dd::Object_table::create_object_table(); |
| 15247 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | innodb_table_stats->set_hidden(false); |
| 15248 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | def = innodb_table_stats->target_table_definition(); |
| 15249 |
2/4✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
|
9622 | def->set_table_name("innodb_table_stats"); |
| 15250 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(0, "database_name", db_field.c_str()); |
| 15251 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(1, "table_name", table_field.c_str()); |
| 15252 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(2, "last_update", |
| 15253 | "last_update TIMESTAMP NOT NULL \n" | ||
| 15254 | " DEFAULT CURRENT_TIMESTAMP \n" | ||
| 15255 | " ON UPDATE CURRENT_TIMESTAMP"); | ||
| 15256 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(3, "n_rows", "n_rows BIGINT UNSIGNED NOT NULL"); |
| 15257 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(4, "clustered_index_size", |
| 15258 | "clustered_index_size BIGINT UNSIGNED NOT NULL"); | ||
| 15259 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(5, "sum_of_other_index_sizes", |
| 15260 | "sum_of_other_index_sizes BIGINT UNSIGNED NOT NULL"); | ||
| 15261 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_index(0, "index_pk", "PRIMARY KEY (database_name, table_name)"); |
| 15262 | /* Options and tablespace are set at the SQL layer. */ | ||
| 15263 | |||
| 15264 | dd::Object_table *innodb_index_stats = | ||
| 15265 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | dd::Object_table::create_object_table(); |
| 15266 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | innodb_index_stats->set_hidden(false); |
| 15267 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | def = innodb_index_stats->target_table_definition(); |
| 15268 |
2/4✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
|
9622 | def->set_table_name("innodb_index_stats"); |
| 15269 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(0, "database_name", db_field.c_str()); |
| 15270 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(1, "table_name", table_field.c_str()); |
| 15271 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(2, "index_name", "index_name VARCHAR(64) NOT NULL"); |
| 15272 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(3, "last_update", |
| 15273 | "last_update TIMESTAMP NOT NULL" | ||
| 15274 | " DEFAULT CURRENT_TIMESTAMP" | ||
| 15275 | " ON UPDATE CURRENT_TIMESTAMP"); | ||
| 15276 | /* | ||
| 15277 | There are at least: stat_name='size' | ||
| 15278 | stat_name='n_leaf_pages' | ||
| 15279 | stat_name='n_diff_pfx%' | ||
| 15280 | */ | ||
| 15281 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(4, "stat_name", "stat_name VARCHAR(64) NOT NULL"); |
| 15282 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(5, "stat_value", "stat_value BIGINT UNSIGNED NOT NULL"); |
| 15283 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(6, "sample_size", "sample_size BIGINT UNSIGNED"); |
| 15284 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(7, "stat_description", |
| 15285 | "stat_description VARCHAR(1024) NOT NULL"); | ||
| 15286 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_index(0, "index_pk", |
| 15287 | "PRIMARY KEY (database_name, table_name, " | ||
| 15288 | "index_name, stat_name)"); | ||
| 15289 | /* Options and tablespace are set at the SQL layer. */ | ||
| 15290 | |||
| 15291 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | dd::Object_table *innodb_ddl_log = dd::Object_table::create_object_table(); |
| 15292 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | innodb_ddl_log->set_hidden(true); |
| 15293 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | def = innodb_ddl_log->target_table_definition(); |
| 15294 |
2/4✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
|
9622 | def->set_table_name("innodb_ddl_log"); |
| 15295 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(0, "id", "id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT"); |
| 15296 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(1, "thread_id", "thread_id BIGINT UNSIGNED NOT NULL"); |
| 15297 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(2, "type", "type INT UNSIGNED NOT NULL"); |
| 15298 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(3, "space_id", "space_id INT UNSIGNED"); |
| 15299 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(4, "page_no", "page_no INT UNSIGNED"); |
| 15300 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(5, "index_id", "index_id BIGINT UNSIGNED"); |
| 15301 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(6, "table_id", "table_id BIGINT UNSIGNED"); |
| 15302 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(7, "old_file_path", |
| 15303 | "old_file_path VARCHAR(512) COLLATE UTF8_BIN"); | ||
| 15304 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_field(8, "new_file_path", |
| 15305 | "new_file_path VARCHAR(512) COLLATE UTF8_BIN"); | ||
| 15306 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_index(0, "index_pk", "PRIMARY KEY(id)"); |
| 15307 |
3/6✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
|
9622 | def->add_index(1, "index_k_thread_id", "KEY(thread_id)"); |
| 15308 | /* Options and tablespace are set at the SQL layer. */ | ||
| 15309 | |||
| 15310 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9602 times.
|
9622 | if (is_dd_encrypted) { |
| 15311 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | innodb_dynamic_metadata->set_target_encrypted(); |
| 15312 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | innodb_table_stats->set_target_encrypted(); |
| 15313 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | innodb_index_stats->set_target_encrypted(); |
| 15314 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | innodb_ddl_log->set_target_encrypted(); |
| 15315 | } | ||
| 15316 | |||
| 15317 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | tables->push_back(innodb_dynamic_metadata); |
| 15318 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | tables->push_back(innodb_table_stats); |
| 15319 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | tables->push_back(innodb_index_stats); |
| 15320 |
1/2✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
|
9622 | tables->push_back(innodb_ddl_log); |
| 15321 | |||
| 15322 |
8/16✓ Branch 0 taken 9622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9622 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9622 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9622 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9622 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9622 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9622 times.
✗ Branch 15 not taken.
|
9622 | LogErr(SYSTEM_LEVEL, ER_IB_MSG_INNODB_END_INITIALIZE); |
| 15323 | |||
| 15324 | 9622 | return false; | |
| 15325 | 9706 | } | |
| 15326 | |||
| 15327 | /** Initialize the set of hard coded DD table ids. | ||
| 15328 | @param[in] dd_table_id Table id of DD table. */ | ||
| 15329 | 328487 | static void innobase_dict_register_dd_table_id(dd::Object_id dd_table_id) { | |
| 15330 | 328487 | dict_sys_t::s_dd_table_ids.insert(dd_table_id); | |
| 15331 | 328487 | } | |
| 15332 | |||
| 15333 | /** Parse the table name into normal name and remote path if needed. | ||
| 15334 | @param[in] name Table name (db/table or full path). | ||
| 15335 | @return 0 if successful, otherwise, error number */ | ||
| 15336 | 352242 | int create_table_info_t::parse_table_name(const char *name) { | |
| 15337 |
1/2✓ Branch 0 taken 352242 times.
✗ Branch 1 not taken.
|
352242 | DBUG_TRACE; |
| 15338 | |||
| 15339 | #ifdef _WIN32 | ||
| 15340 | /* Names passed in from server are in two formats: | ||
| 15341 | 1. <database_name>/<table_name>: for normal table creation | ||
| 15342 | 2. full path: for temp table creation, or DATA DIRECTORY. | ||
| 15343 | |||
| 15344 | When srv_file_per_table is on, | ||
| 15345 | check for full path pattern, i.e. | ||
| 15346 | X:\dir\..., X is a driver letter, or | ||
| 15347 | \\dir1\dir2\..., UNC path | ||
| 15348 | returns error if it is in full path format, but not creating a temp. | ||
| 15349 | table. Currently InnoDB does not support symbolic link on Windows. */ | ||
| 15350 | |||
| 15351 | if (m_innodb_file_per_table && | ||
| 15352 | !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE)) { | ||
| 15353 | if (name[1] == ':' || (name[0] == '\\' && name[1] == '\\')) { | ||
| 15354 | log_errlog(ERROR_LEVEL, ER_INNODB_CANNOT_CREATE_TABLE, name); | ||
| 15355 | return HA_ERR_GENERIC; | ||
| 15356 | } | ||
| 15357 | } | ||
| 15358 | #endif /* _WIN32 */ | ||
| 15359 | |||
| 15360 |
2/4✓ Branch 0 taken 352241 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 352241 times.
|
352242 | if (!normalize_table_name(m_table_name, name)) { |
| 15361 | /* purecov: begin inspected */ | ||
| 15362 | ✗ | ut_d(ut_error); | |
| 15363 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 15364 | /* purecov: end */ | ||
| 15365 | } | ||
| 15366 | |||
| 15367 | 352241 | m_remote_path[0] = '\0'; | |
| 15368 | 352241 | m_tablespace[0] = '\0'; | |
| 15369 | |||
| 15370 | /* Set the remote path if DATA DIRECTORY is valid. If not, | ||
| 15371 | we ignore the DATA DIRECTORY. In strict mode, a non-valid | ||
| 15372 | value would have already been rejected. */ | ||
| 15373 |
2/2✓ Branch 0 taken 23582 times.
✓ Branch 1 taken 328659 times.
|
352241 | if (m_create_info->data_file_name != nullptr && |
| 15374 |
3/4✓ Branch 0 taken 468 times.
✓ Branch 1 taken 23114 times.
✓ Branch 2 taken 468 times.
✗ Branch 3 not taken.
|
23582 | *m_create_info->data_file_name != '\0' && m_table_name != nullptr) { |
| 15375 |
3/4✓ Branch 0 taken 468 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 455 times.
|
468 | if (!create_option_data_directory_is_valid(true)) { |
| 15376 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
13 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED, |
| 15377 | ER_DEFAULT(WARN_OPTION_IGNORED), "DATA DIRECTORY"); | ||
| 15378 | 13 | m_flags &= ~DICT_TF_MASK_DATA_DIR; | |
| 15379 | } else { | ||
| 15380 | 455 | strncpy(m_remote_path, m_create_info->data_file_name, FN_REFLEN - 1); | |
| 15381 | } | ||
| 15382 | } | ||
| 15383 | |||
| 15384 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 352203 times.
|
352241 | if (m_create_info->index_file_name) { |
| 15385 |
2/4✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
38 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED, |
| 15386 | ER_DEFAULT(WARN_OPTION_IGNORED), "INDEX DIRECTORY"); | ||
| 15387 | } | ||
| 15388 | |||
| 15389 | /* The TABLESPACE designation has already been validated by | ||
| 15390 | create_option_tablespace_is_valid() irregardless of strict-mode. | ||
| 15391 | So it only needs to be copied now. */ | ||
| 15392 |
2/2✓ Branch 0 taken 24392 times.
✓ Branch 1 taken 327849 times.
|
352241 | if (m_use_shared_space) { |
| 15393 | 24392 | strncpy(m_tablespace, m_create_info->tablespace, NAME_LEN - 1); | |
| 15394 | } | ||
| 15395 | |||
| 15396 | 352240 | return 0; | |
| 15397 | 352241 | } | |
| 15398 | |||
| 15399 | /** Determine InnoDB table flags. | ||
| 15400 | If strict_mode=OFF, this will adjust the flags to what should be assumed. | ||
| 15401 | However, if an existing general tablespace is being targeted, we will NOT | ||
| 15402 | assume anything or adjust these flags. | ||
| 15403 | @retval true if successful, false if error */ | ||
| 15404 | 395991 | bool create_table_info_t::innobase_table_flags() { | |
| 15405 |
1/2✓ Branch 0 taken 395992 times.
✗ Branch 1 not taken.
|
395991 | DBUG_TRACE; |
| 15406 | |||
| 15407 | 395992 | const char *fts_doc_id_index_bad = nullptr; | |
| 15408 | 395992 | uint32_t zip_ssize = 0; | |
| 15409 | 395992 | const bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 15410 | 395992 | bool zip_allowed = !is_temp; | |
| 15411 | |||
| 15412 | const uint32_t zip_ssize_max = | ||
| 15413 | 395992 | std::min<uint32_t>((UNIV_PAGE_SSIZE_MAX), (PAGE_ZIP_SSIZE_MAX)); | |
| 15414 | |||
| 15415 | 395992 | m_flags = 0; | |
| 15416 | 395992 | m_flags2 = 0; | |
| 15417 | |||
| 15418 | /* Validate the page compression parameter. */ | ||
| 15419 |
1/2✓ Branch 0 taken 395992 times.
✗ Branch 1 not taken.
|
395992 | if (!create_option_compression_is_valid()) { |
| 15420 | /* No need to do anything. Warnings were issued. | ||
| 15421 | The compresion setting will be ignored later. | ||
| 15422 | If inodb_strict_mode=ON, this is called twice unless | ||
| 15423 | there was a problem before. | ||
| 15424 | If inodb_strict_mode=OFF, this is the only call. */ | ||
| 15425 | } | ||
| 15426 | |||
| 15427 | /* Validate the page encryption parameter. */ | ||
| 15428 |
2/2✓ Branch 0 taken 84366 times.
✓ Branch 1 taken 311626 times.
|
395992 | if (m_create_info->encrypt_type.length > 0) { |
| 15429 | 84366 | const char *encryption = m_create_info->encrypt_type.str; | |
| 15430 | |||
| 15431 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84366 times.
|
84366 | if (Encryption::validate(encryption) != DB_SUCCESS) { |
| 15432 | /* Incorrect encryption option */ | ||
| 15433 | ✗ | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); | |
| 15434 | ✗ | return false; | |
| 15435 | } | ||
| 15436 | } | ||
| 15437 | |||
| 15438 | /* Check if there are any FTS indexes defined on this table. */ | ||
| 15439 |
2/2✓ Branch 0 taken 227023 times.
✓ Branch 1 taken 395989 times.
|
623012 | for (uint i = 0; i < m_form->s->keys; i++) { |
| 15440 | 227023 | const KEY *key = &m_form->key_info[i]; | |
| 15441 | |||
| 15442 |
2/2✓ Branch 0 taken 2027 times.
✓ Branch 1 taken 224996 times.
|
227023 | if (key->flags & HA_FULLTEXT) { |
| 15443 | 2027 | m_flags2 |= DICT_TF2_FTS; | |
| 15444 | |||
| 15445 | /* We don't support FTS indexes in temporary | ||
| 15446 | tables. */ | ||
| 15447 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2026 times.
|
2027 | if (is_temp) { |
| 15448 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error(ER_INNODB_NO_FT_TEMP_TABLE, MYF(0)); |
| 15449 | 1 | return false; | |
| 15450 | } | ||
| 15451 | |||
| 15452 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2024 times.
|
2026 | if (fts_doc_id_index_bad) { |
| 15453 | 2 | goto index_bad; | |
| 15454 | } | ||
| 15455 |
2/2✓ Branch 0 taken 583 times.
✓ Branch 1 taken 224413 times.
|
224996 | } else if (key->flags & HA_SPATIAL) { |
| 15456 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 583 times.
|
583 | assert(~m_create_info->options & |
| 15457 | (HA_LEX_CREATE_TMP_TABLE | HA_LEX_CREATE_INTERNAL_TMP_TABLE)); | ||
| 15458 | } | ||
| 15459 | |||
| 15460 |
3/4✓ Branch 0 taken 227020 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 226972 times.
✓ Branch 3 taken 48 times.
|
227020 | if (innobase_strcasecmp(key->name, FTS_DOC_ID_INDEX_NAME)) { |
| 15461 | 226972 | continue; | |
| 15462 | } | ||
| 15463 | |||
| 15464 | /* Do a pre-check on FTS DOC ID index */ | ||
| 15465 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | if (!(key->flags & HA_NOSAME) |
| 15466 | /* For now, we do not allow a descending index, | ||
| 15467 | because fts_doc_fetch_by_doc_id() uses the | ||
| 15468 | InnODB SQL interpreter to look up FTS_DOC_ID.*/ | ||
| 15469 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 5 times.
|
48 | || (key->key_part[0].key_part_flag & HA_REVERSE_SORT) || |
| 15470 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | strcmp(key->name, FTS_DOC_ID_INDEX_NAME) || |
| 15471 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
|
43 | strcmp(key->key_part[0].field->field_name, FTS_DOC_ID_COL_NAME)) { |
| 15472 | 7 | fts_doc_id_index_bad = key->name; | |
| 15473 | } | ||
| 15474 | |||
| 15475 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
48 | if (fts_doc_id_index_bad && (m_flags2 & DICT_TF2_FTS)) { |
| 15476 | ✗ | index_bad: | |
| 15477 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0), fts_doc_id_index_bad); |
| 15478 | 2 | return false; | |
| 15479 | } | ||
| 15480 | } | ||
| 15481 | |||
| 15482 |
4/4✓ Branch 0 taken 153491 times.
✓ Branch 1 taken 242498 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 153475 times.
|
395989 | if (is_temp && m_create_info->key_block_size > 0) { |
| 15483 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, |
| 15484 | "InnoDB: KEY_BLOCK_SIZE is ignored" | ||
| 15485 | " for TEMPORARY TABLE."); | ||
| 15486 | 16 | zip_allowed = false; | |
| 15487 |
2/2✓ Branch 0 taken 409 times.
✓ Branch 1 taken 395564 times.
|
395973 | } else if (m_create_info->key_block_size > 0) { |
| 15488 |
1/2✓ Branch 0 taken 409 times.
✗ Branch 1 not taken.
|
409 | zip_ssize = get_zip_shift_size(m_create_info->key_block_size); |
| 15489 | |||
| 15490 | /* Make sure compressed row format is allowed. */ | ||
| 15491 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 409 times.
|
409 | if (is_temp) { |
| 15492 | ✗ | push_warning(m_thd, Sql_condition::SL_WARNING, | |
| 15493 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15494 | "InnoDB: KEY_BLOCK_SIZE is ignored" | ||
| 15495 | " for TEMPORARY TABLE."); | ||
| 15496 | ✗ | zip_allowed = false; | |
| 15497 |
3/4✓ Branch 0 taken 15 times.
✓ Branch 1 taken 394 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
409 | } else if (!m_allow_file_per_table && !m_use_shared_space) { |
| 15498 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | push_warning(m_thd, Sql_condition::SL_WARNING, |
| 15499 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15500 | "InnoDB: KEY_BLOCK_SIZE requires" | ||
| 15501 | " innodb_file_per_table."); | ||
| 15502 | 15 | zip_allowed = false; | |
| 15503 | } | ||
| 15504 | |||
| 15505 |
5/6✓ Branch 0 taken 394 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 392 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
409 | if (!zip_allowed || (!zip_ssize && m_create_info->key_block_size)) { |
| 15506 | 17 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 15507 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15508 | "InnoDB: ignoring KEY_BLOCK_SIZE=%" PRIu32 ".", | ||
| 15509 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | m_create_info->key_block_size); |
| 15510 | } | ||
| 15511 | } | ||
| 15512 | |||
| 15513 | 395989 | enum row_type row_type = m_form->s->row_type; | |
| 15514 | |||
| 15515 |
4/4✓ Branch 0 taken 406 times.
✓ Branch 1 taken 395583 times.
✓ Branch 2 taken 392 times.
✓ Branch 3 taken 14 times.
|
395989 | if (zip_ssize && zip_allowed) { |
| 15516 | /* if ROW_FORMAT is set to default, | ||
| 15517 | automatically change it to COMPRESSED. */ | ||
| 15518 |
2/2✓ Branch 0 taken 115 times.
✓ Branch 1 taken 277 times.
|
392 | if (row_type == ROW_TYPE_DEFAULT) { |
| 15519 | 115 | row_type = ROW_TYPE_COMPRESSED; | |
| 15520 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 261 times.
|
277 | } else if (row_type != ROW_TYPE_COMPRESSED) { |
| 15521 | /* ROW_FORMAT other than COMPRESSED | ||
| 15522 | ignores KEY_BLOCK_SIZE. It does not | ||
| 15523 | make sense to reject conflicting | ||
| 15524 | KEY_BLOCK_SIZE and ROW_FORMAT, because | ||
| 15525 | such combinations can be obtained | ||
| 15526 | with ALTER TABLE anyway. */ | ||
| 15527 | 16 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 15528 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15529 | "InnoDB: ignoring KEY_BLOCK_SIZE=%" PRIu32 | ||
| 15530 | " as ROW_FORMAT is not COMPRESSED.", | ||
| 15531 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | m_create_info->key_block_size); |
| 15532 | 16 | zip_allowed = false; | |
| 15533 | } | ||
| 15534 | } else { | ||
| 15535 | /* zip_ssize == 0 means no KEY_BLOCK_SIZE. */ | ||
| 15536 |
4/4✓ Branch 0 taken 665 times.
✓ Branch 1 taken 394932 times.
✓ Branch 2 taken 643 times.
✓ Branch 3 taken 22 times.
|
395597 | if (row_type == ROW_TYPE_COMPRESSED && zip_allowed) { |
| 15537 | /* ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE | ||
| 15538 | implies half the maximum KEY_BLOCK_SIZE(*1k) or | ||
| 15539 | UNIV_PAGE_SIZE, whichever is less. */ | ||
| 15540 | 643 | zip_ssize = zip_ssize_max - 1; | |
| 15541 | } | ||
| 15542 | } | ||
| 15543 | |||
| 15544 |
1/2✓ Branch 0 taken 395987 times.
✗ Branch 1 not taken.
|
395989 | rec_format_t innodb_row_format = get_row_format(innodb_default_row_format); |
| 15545 |
6/7✓ Branch 0 taken 1230 times.
✓ Branch 1 taken 1374 times.
✓ Branch 2 taken 1041 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 36919 times.
✓ Branch 5 taken 355418 times.
✗ Branch 6 not taken.
|
395987 | switch (row_type) { |
| 15546 | 1230 | case ROW_TYPE_REDUNDANT: | |
| 15547 | 1230 | innodb_row_format = REC_FORMAT_REDUNDANT; | |
| 15548 | 1230 | break; | |
| 15549 | 1374 | case ROW_TYPE_COMPACT: | |
| 15550 | 1374 | innodb_row_format = REC_FORMAT_COMPACT; | |
| 15551 | 1374 | break; | |
| 15552 | |||
| 15553 | 1041 | case ROW_TYPE_COMPRESSED: | |
| 15554 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1026 times.
|
1041 | if (is_temp) { |
| 15555 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, |
| 15556 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15557 | "InnoDB: %s is ignored for TEMPORARY TABLE.", | ||
| 15558 | get_row_format_name(row_type)); | ||
| 15559 | |||
| 15560 | /* DYNAMIC row format is closer to COMPRESSED | ||
| 15561 | in that it supports better for large BLOBs. */ | ||
| 15562 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | push_warning(m_thd, Sql_condition::SL_WARNING, |
| 15563 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15564 | "InnoDB: assuming ROW_FORMAT=DYNAMIC."); | ||
| 15565 | |||
| 15566 | 15 | row_type = ROW_TYPE_DYNAMIC; | |
| 15567 | 15 | innodb_row_format = REC_FORMAT_DYNAMIC; | |
| 15568 | 15 | break; | |
| 15569 | } | ||
| 15570 | |||
| 15571 | /* ROW_FORMAT=COMPRESSED requires file_per_table unless | ||
| 15572 | there is a target tablespace. */ | ||
| 15573 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1018 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
1026 | if (!m_allow_file_per_table && !m_use_shared_space) { |
| 15574 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, |
| 15575 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15576 | "InnoDB: %s requires innodb_file_per_table.", | ||
| 15577 | get_row_format_name(row_type)); | ||
| 15578 | } else { | ||
| 15579 | /* We can use this row_format. */ | ||
| 15580 | 1018 | innodb_row_format = REC_FORMAT_COMPRESSED; | |
| 15581 | 1018 | break; | |
| 15582 | } | ||
| 15583 | 8 | zip_allowed = false; | |
| 15584 | /* fall through to set row_type = DYNAMIC */ | ||
| 15585 | [[fallthrough]]; | ||
| 15586 | 13 | case ROW_TYPE_NOT_USED: | |
| 15587 | case ROW_TYPE_FIXED: | ||
| 15588 | case ROW_TYPE_PAGED: | ||
| 15589 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | push_warning(m_thd, Sql_condition::SL_WARNING, |
| 15590 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15591 | "InnoDB: assuming ROW_FORMAT=DYNAMIC."); | ||
| 15592 | [[fallthrough]]; | ||
| 15593 | 36932 | case ROW_TYPE_DYNAMIC: | |
| 15594 | 36932 | innodb_row_format = REC_FORMAT_DYNAMIC; | |
| 15595 | 36932 | break; | |
| 15596 | 355418 | case ROW_TYPE_DEFAULT: { | |
| 15597 | /* Consider the real_row_type if already set. */ | ||
| 15598 |
4/5✓ Branch 0 taken 27 times.
✓ Branch 1 taken 153 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 355159 times.
✓ Branch 4 taken 79 times.
|
355418 | switch (m_form->s->real_row_type) { |
| 15599 | 27 | case ROW_TYPE_REDUNDANT: | |
| 15600 | 27 | innodb_row_format = REC_FORMAT_REDUNDANT; | |
| 15601 | 27 | break; | |
| 15602 | 153 | case ROW_TYPE_COMPACT: | |
| 15603 | 153 | innodb_row_format = REC_FORMAT_COMPACT; | |
| 15604 | 153 | break; | |
| 15605 | ✗ | case ROW_TYPE_COMPRESSED: | |
| 15606 | ✗ | innodb_row_format = REC_FORMAT_COMPRESSED; | |
| 15607 | ✗ | break; | |
| 15608 | 355159 | case ROW_TYPE_DYNAMIC: | |
| 15609 | 355159 | innodb_row_format = REC_FORMAT_DYNAMIC; | |
| 15610 | 355159 | break; | |
| 15611 | 79 | default: | |
| 15612 | 79 | break; | |
| 15613 | } | ||
| 15614 | 355418 | break; | |
| 15615 | } | ||
| 15616 | ✗ | default: | |
| 15617 | ✗ | ut_d(ut_error); | |
| 15618 | } | ||
| 15619 | |||
| 15620 | /* Don't support compressed table when page size > 16k. */ | ||
| 15621 |
5/6✓ Branch 0 taken 242466 times.
✓ Branch 1 taken 153521 times.
✓ Branch 2 taken 1018 times.
✓ Branch 3 taken 241448 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1018 times.
|
395987 | if (zip_allowed && zip_ssize && UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) { |
| 15622 | ✗ | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, | |
| 15623 | "InnoDB: Cannot create a COMPRESSED table" | ||
| 15624 | " when innodb_page_size > 16k." | ||
| 15625 | " Assuming ROW_FORMAT=DYNAMIC."); | ||
| 15626 | ✗ | zip_allowed = false; | |
| 15627 | } | ||
| 15628 | |||
| 15629 |
4/6✓ Branch 0 taken 153490 times.
✓ Branch 1 taken 242497 times.
✓ Branch 2 taken 153490 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 395989 times.
|
395987 | ut_ad(!is_temp || !zip_allowed); |
| 15630 |
4/6✓ Branch 0 taken 153491 times.
✓ Branch 1 taken 242498 times.
✓ Branch 2 taken 153491 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 395988 times.
|
395989 | ut_ad(!is_temp || row_type != ROW_TYPE_COMPRESSED); |
| 15631 |
5/6✓ Branch 0 taken 153490 times.
✓ Branch 1 taken 242498 times.
✓ Branch 2 taken 153490 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 395987 times.
|
395988 | ut_ad(!is_temp || innodb_row_format != REC_FORMAT_COMPRESSED); |
| 15632 | |||
| 15633 | /* Set the table flags */ | ||
| 15634 |
2/2✓ Branch 0 taken 153523 times.
✓ Branch 1 taken 242464 times.
|
395987 | if (!zip_allowed) { |
| 15635 | 153523 | zip_ssize = 0; | |
| 15636 | } | ||
| 15637 | |||
| 15638 |
2/2✓ Branch 0 taken 153490 times.
✓ Branch 1 taken 242497 times.
|
395987 | if (is_temp) { |
| 15639 | 153490 | m_flags2 |= DICT_TF2_TEMPORARY; | |
| 15640 | |||
| 15641 |
2/2✓ Branch 0 taken 110977 times.
✓ Branch 1 taken 42513 times.
|
153490 | if (m_create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE) { |
| 15642 | /* Intrinsic tables reside only in the shared temporary | ||
| 15643 | tablespace and we will always use ROW_FORMAT=DYNAMIC. */ | ||
| 15644 | /* We do not allow compressed instrinsic temporary tables. */ | ||
| 15645 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 110977 times.
|
110977 | ut_ad(zip_ssize == 0); |
| 15646 | 110977 | innodb_row_format = REC_FORMAT_DYNAMIC; | |
| 15647 | 110977 | m_flags2 |= DICT_TF2_INTRINSIC; | |
| 15648 | } | ||
| 15649 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 153481 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
153490 | if (m_use_shared_space && m_create_info->tablespace != nullptr && |
| 15650 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | strcmp(m_create_info->tablespace, dict_sys_t::s_temp_space_name) == 0) { |
| 15651 | /* This is possible only with innodb_strict_mode=OFF and we warned that | ||
| 15652 | that tablespace=innodb_temporary is ignored. We should instead use | ||
| 15653 | session temporary tablespaces */ | ||
| 15654 | 9 | m_use_shared_space = false; | |
| 15655 | } | ||
| 15656 | |||
| 15657 |
2/2✓ Branch 0 taken 195884 times.
✓ Branch 1 taken 46613 times.
|
242497 | } else if (m_use_file_per_table) { |
| 15658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 195885 times.
|
195884 | ut_ad(!m_use_shared_space); |
| 15659 | 195885 | m_flags2 |= DICT_TF2_USE_FILE_PER_TABLE; | |
| 15660 | } | ||
| 15661 | |||
| 15662 | /* Set the table flags */ | ||
| 15663 | 395988 | dict_tf_set(&m_flags, innodb_row_format, zip_ssize, m_use_data_dir, | |
| 15664 |
1/2✓ Branch 0 taken 395989 times.
✗ Branch 1 not taken.
|
395988 | m_use_shared_space); |
| 15665 | |||
| 15666 | 395989 | return true; | |
| 15667 | 395992 | } | |
| 15668 | |||
| 15669 | /** Detach the just created table and its auxiliary tables if exist */ | ||
| 15670 | 176425 | void create_table_info_t::detach() { | |
| 15671 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 176425 times.
|
176425 | ut_ad(!dict_sys_mutex_own()); |
| 15672 | 176425 | dict_sys_mutex_enter(); | |
| 15673 | |||
| 15674 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 176425 times.
|
176425 | ut_ad(m_table != nullptr); |
| 15675 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 176425 times.
|
176425 | ut_ad(!m_table->can_be_evicted); |
| 15676 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 176425 times.
|
176425 | ut_ad(!m_table->is_temporary()); |
| 15677 | |||
| 15678 |
2/2✓ Branch 0 taken 166563 times.
✓ Branch 1 taken 9862 times.
|
176425 | if (!m_table->explicitly_non_lru) { |
| 15679 | 166563 | dict_table_allow_eviction(m_table); | |
| 15680 | } | ||
| 15681 | |||
| 15682 |
2/2✓ Branch 0 taken 176005 times.
✓ Branch 1 taken 420 times.
|
176425 | if ((m_table->flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) || |
| 15683 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 176005 times.
|
176005 | m_table->fts != nullptr) { |
| 15684 | 420 | fts_detach_aux_tables(m_table, true); | |
| 15685 | } | ||
| 15686 | |||
| 15687 | 176425 | dict_sys_mutex_exit(); | |
| 15688 | 176425 | } | |
| 15689 | |||
| 15690 | /** Parse MERGE_THRESHOLD value from the string. | ||
| 15691 | @param[in] thd connection | ||
| 15692 | @param[in] str string which might include 'MERGE_THRESHOLD=' | ||
| 15693 | @return value parsed. 0 means not found or invalid value. */ | ||
| 15694 | 33676 | static ulint innobase_parse_merge_threshold(THD *thd, const char *str) { | |
| 15695 | static const char *label = "MERGE_THRESHOLD="; | ||
| 15696 |
3/4✓ Branch 0 taken 470 times.
✓ Branch 1 taken 33206 times.
✓ Branch 2 taken 470 times.
✗ Branch 3 not taken.
|
33676 | static const size_t label_len = strlen(label); |
| 15697 | 33676 | const char *pos = str; | |
| 15698 | |||
| 15699 | 33676 | pos = strstr(str, label); | |
| 15700 | |||
| 15701 |
2/2✓ Branch 0 taken 33601 times.
✓ Branch 1 taken 75 times.
|
33676 | if (pos == nullptr) { |
| 15702 | 33601 | return (0); | |
| 15703 | } | ||
| 15704 | |||
| 15705 | 75 | pos += label_len; | |
| 15706 | |||
| 15707 | 75 | lint ret = atoi(pos); | |
| 15708 | |||
| 15709 |
4/4✓ Branch 0 taken 66 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 10 times.
|
75 | if (ret > 0 && ret <= 50) { |
| 15710 | 56 | return (static_cast<ulint>(ret)); | |
| 15711 | } | ||
| 15712 | |||
| 15713 | 19 | push_warning_printf( | |
| 15714 | thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 15715 | "InnoDB: Invalid value for MERGE_THRESHOLD in the CREATE TABLE" | ||
| 15716 | " statement. The value is ignored."); | ||
| 15717 | |||
| 15718 | 19 | return (0); | |
| 15719 | } | ||
| 15720 | |||
| 15721 | /** Parse hint for table and its indexes, and update the information | ||
| 15722 | in dictionary. | ||
| 15723 | @param[in] thd Connection thread | ||
| 15724 | @param[in,out] table Target table | ||
| 15725 | @param[in] table_share Table definition */ | ||
| 15726 | 401063 | void innobase_parse_hint_from_comment(THD *thd, dict_table_t *table, | |
| 15727 | const TABLE_SHARE *table_share) { | ||
| 15728 | ulint merge_threshold_table; | ||
| 15729 | ulint merge_threshold_index[MAX_KEY]; | ||
| 15730 | bool is_found[MAX_KEY]; | ||
| 15731 | |||
| 15732 |
2/2✓ Branch 0 taken 33440 times.
✓ Branch 1 taken 367623 times.
|
401063 | if (table_share->comment.str != nullptr) { |
| 15733 | merge_threshold_table = | ||
| 15734 |
1/2✓ Branch 0 taken 33440 times.
✗ Branch 1 not taken.
|
33440 | innobase_parse_merge_threshold(thd, table_share->comment.str); |
| 15735 | } else { | ||
| 15736 | 367623 | merge_threshold_table = DICT_INDEX_MERGE_THRESHOLD_DEFAULT; | |
| 15737 | } | ||
| 15738 | |||
| 15739 |
2/2✓ Branch 0 taken 33430 times.
✓ Branch 1 taken 367633 times.
|
401063 | if (merge_threshold_table == 0) { |
| 15740 | 33430 | merge_threshold_table = DICT_INDEX_MERGE_THRESHOLD_DEFAULT; | |
| 15741 | } | ||
| 15742 | |||
| 15743 |
2/2✓ Branch 0 taken 241504 times.
✓ Branch 1 taken 401063 times.
|
642567 | for (uint i = 0; i < table_share->keys; i++) { |
| 15744 | 241504 | KEY *key_info = &table_share->key_info[i]; | |
| 15745 | |||
| 15746 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 241504 times.
|
241504 | ut_ad(i < sizeof(merge_threshold_index) / sizeof(merge_threshold_index[0])); |
| 15747 | |||
| 15748 |
3/4✓ Branch 0 taken 236 times.
✓ Branch 1 taken 241268 times.
✓ Branch 2 taken 236 times.
✗ Branch 3 not taken.
|
241504 | if (key_info->flags & HA_USES_COMMENT && key_info->comment.str != nullptr) { |
| 15749 | 236 | merge_threshold_index[i] = | |
| 15750 |
1/2✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
|
236 | innobase_parse_merge_threshold(thd, key_info->comment.str); |
| 15751 | } else { | ||
| 15752 | 241268 | merge_threshold_index[i] = merge_threshold_table; | |
| 15753 | } | ||
| 15754 | |||
| 15755 |
2/2✓ Branch 0 taken 190 times.
✓ Branch 1 taken 241314 times.
|
241504 | if (merge_threshold_index[i] == 0) { |
| 15756 | 190 | merge_threshold_index[i] = merge_threshold_table; | |
| 15757 | } | ||
| 15758 | } | ||
| 15759 | |||
| 15760 |
2/2✓ Branch 0 taken 241504 times.
✓ Branch 1 taken 401063 times.
|
642567 | for (uint i = 0; i < table_share->keys; i++) { |
| 15761 | 241504 | is_found[i] = false; | |
| 15762 | } | ||
| 15763 | |||
| 15764 | /* update in memory */ | ||
| 15765 |
6/10✓ Branch 0 taken 401063 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 401063 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 505085 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 906148 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 505085 times.
✓ Branch 9 taken 401063 times.
|
906148 | for (auto index : table->indexes) { |
| 15766 |
2/2✓ Branch 0 taken 262627 times.
✓ Branch 1 taken 242458 times.
|
505085 | if (dict_index_is_auto_gen_clust(index)) { |
| 15767 | /* GEN_CLUST_INDEX should use merge_threshold_table */ | ||
| 15768 | |||
| 15769 | /* x-lock index is needed to exclude concurrent | ||
| 15770 | pessimistic tree operations */ | ||
| 15771 |
2/4✓ Branch 0 taken 262627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262627 times.
✗ Branch 3 not taken.
|
262627 | rw_lock_x_lock(dict_index_get_lock(index), UT_LOCATION_HERE); |
| 15772 | 262627 | index->merge_threshold = merge_threshold_table; | |
| 15773 |
2/4✓ Branch 0 taken 262627 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 262627 times.
✗ Branch 3 not taken.
|
262627 | rw_lock_x_unlock(dict_index_get_lock(index)); |
| 15774 | |||
| 15775 | 262627 | continue; | |
| 15776 | } | ||
| 15777 | |||
| 15778 |
2/2✓ Branch 0 taken 513376 times.
✓ Branch 1 taken 978 times.
|
514354 | for (uint i = 0; i < table_share->keys; i++) { |
| 15779 |
2/2✓ Branch 0 taken 269910 times.
✓ Branch 1 taken 243466 times.
|
513376 | if (is_found[i]) { |
| 15780 | 269910 | continue; | |
| 15781 | } | ||
| 15782 | |||
| 15783 | 243466 | KEY *key_info = &table_share->key_info[i]; | |
| 15784 | |||
| 15785 |
3/4✓ Branch 0 taken 243466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241480 times.
✓ Branch 3 taken 1986 times.
|
243466 | if (innobase_strcasecmp(index->name, key_info->name) == 0) { |
| 15786 | /* x-lock index is needed to exclude concurrent | ||
| 15787 | pessimistic tree operations */ | ||
| 15788 |
2/4✓ Branch 0 taken 241480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241480 times.
✗ Branch 3 not taken.
|
241480 | rw_lock_x_lock(dict_index_get_lock(index), UT_LOCATION_HERE); |
| 15789 | 241480 | index->merge_threshold = merge_threshold_index[i]; | |
| 15790 |
2/4✓ Branch 0 taken 241480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241480 times.
✗ Branch 3 not taken.
|
241480 | rw_lock_x_unlock(dict_index_get_lock(index)); |
| 15791 | 241480 | is_found[i] = true; | |
| 15792 | |||
| 15793 | 241480 | break; | |
| 15794 | } | ||
| 15795 | } | ||
| 15796 | } | ||
| 15797 | 401063 | } | |
| 15798 | |||
| 15799 | /** Set m_use_* flags. */ | ||
| 15800 | 412514 | void create_table_info_t::set_tablespace_type( | |
| 15801 | bool table_being_altered_is_file_per_table) { | ||
| 15802 | /* Note whether this table will be created using a shared, | ||
| 15803 | general or system tablespace. */ | ||
| 15804 | 412514 | m_use_shared_space = tablespace_is_shared_space(m_create_info); | |
| 15805 | |||
| 15806 | /** Allow file_per_table for this table either because: | ||
| 15807 | 1) the setting innodb_file_per_table=on, | ||
| 15808 | 2) the table being altered is currently file_per_table | ||
| 15809 | 3) explicitly requested by tablespace=innodb_file_per_table. */ | ||
| 15810 |
1/2✓ Branch 0 taken 25280 times.
✗ Branch 1 not taken.
|
25280 | m_allow_file_per_table = m_innodb_file_per_table || |
| 15811 |
4/4✓ Branch 0 taken 25280 times.
✓ Branch 1 taken 387234 times.
✓ Branch 2 taken 136 times.
✓ Branch 3 taken 25144 times.
|
437794 | table_being_altered_is_file_per_table || |
| 15812 | 25280 | tablespace_is_file_per_table(m_create_info); | |
| 15813 | |||
| 15814 | 412514 | bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 15815 | |||
| 15816 | /* Ignore the current innodb_file_per_table setting if we are | ||
| 15817 | creating a temporary table or if the | ||
| 15818 | TABLESPACE= phrase is using an existing shared tablespace. */ | ||
| 15819 | 412514 | m_use_file_per_table = | |
| 15820 |
6/6✓ Branch 0 taken 387371 times.
✓ Branch 1 taken 25143 times.
✓ Branch 2 taken 234054 times.
✓ Branch 3 taken 153317 times.
✓ Branch 4 taken 209573 times.
✓ Branch 5 taken 24481 times.
|
412514 | m_allow_file_per_table && !is_temp && !m_use_shared_space; |
| 15821 | |||
| 15822 | /* DATA DIRECTORY must have m_use_file_per_table. */ | ||
| 15823 | 1034602 | m_use_data_dir = m_use_file_per_table && | |
| 15824 |
4/4✓ Branch 0 taken 209574 times.
✓ Branch 1 taken 202940 times.
✓ Branch 2 taken 20679 times.
✓ Branch 3 taken 188895 times.
|
433193 | (m_create_info->data_file_name != nullptr) && |
| 15825 |
2/2✓ Branch 0 taken 645 times.
✓ Branch 1 taken 20034 times.
|
20679 | (m_create_info->data_file_name[0] != '\0'); |
| 15826 |
4/6✓ Branch 0 taken 44844 times.
✓ Branch 1 taken 367670 times.
✓ Branch 2 taken 44844 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 412515 times.
|
412514 | ut_ad(!(m_use_shared_space && m_use_data_dir)); |
| 15827 | 412515 | } | |
| 15828 | |||
| 15829 | /** Initialize the create_table_info_t object. | ||
| 15830 | @return error number */ | ||
| 15831 | 325062 | int create_table_info_t::initialize() { | |
| 15832 |
1/2✓ Branch 0 taken 325063 times.
✗ Branch 1 not taken.
|
325062 | DBUG_TRACE; |
| 15833 | |||
| 15834 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 325063 times.
|
325063 | ut_ad(m_thd != nullptr); |
| 15835 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 325062 times.
|
325063 | ut_ad(m_create_info != nullptr); |
| 15836 | |||
| 15837 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 325052 times.
|
325062 | if (m_form->s->fields > REC_MAX_N_USER_FIELDS) { |
| 15838 | 10 | return HA_ERR_TOO_MANY_FIELDS; | |
| 15839 | } | ||
| 15840 | |||
| 15841 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 325053 times.
|
325052 | ut_ad(m_form->s->row_type == m_create_info->row_type); |
| 15842 | |||
| 15843 | /* Check for name conflicts (with reserved name) for | ||
| 15844 | any user indices to be created. */ | ||
| 15845 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 325050 times.
|
325052 | if (innobase_index_name_is_reserved(m_thd, m_form->key_info, |
| 15846 |
1/2✓ Branch 0 taken 325052 times.
✗ Branch 1 not taken.
|
325053 | m_form->s->keys)) { |
| 15847 | 2 | return HA_ERR_WRONG_INDEX; | |
| 15848 | } | ||
| 15849 | |||
| 15850 | 325050 | m_trx->will_lock++; | |
| 15851 | |||
| 15852 | 325050 | m_table = nullptr; | |
| 15853 | |||
| 15854 | 325050 | return 0; | |
| 15855 | 325062 | } | |
| 15856 | |||
| 15857 | /** Initialize the autoinc of this table if necessary, which should | ||
| 15858 | be called before we flush logs, so autoinc counter can be persisted. */ | ||
| 15859 | 347993 | void create_table_info_t::initialize_autoinc() { | |
| 15860 | dict_table_t *innobase_table; | ||
| 15861 | |||
| 15862 |
2/2✓ Branch 0 taken 194477 times.
✓ Branch 1 taken 153516 times.
|
542470 | const bool persist = !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE) && |
| 15863 |
2/2✓ Branch 0 taken 15712 times.
✓ Branch 1 taken 178765 times.
|
194477 | m_form->found_next_number_field; |
| 15864 | |||
| 15865 |
4/4✓ Branch 0 taken 332281 times.
✓ Branch 1 taken 15712 times.
✓ Branch 2 taken 331502 times.
✓ Branch 3 taken 779 times.
|
347993 | if (!persist && m_create_info->auto_increment_value == 0) { |
| 15866 | 331502 | return; | |
| 15867 | } | ||
| 15868 | |||
| 15869 | innobase_table = | ||
| 15870 | 16491 | thd_to_innodb_session(m_thd)->lookup_table_handler(m_table_name); | |
| 15871 | |||
| 15872 |
1/2✓ Branch 0 taken 16491 times.
✗ Branch 1 not taken.
|
16491 | if (innobase_table == nullptr) { |
| 15873 | 16491 | innobase_table = dd_table_open_on_name_in_mem(m_table_name, false); | |
| 15874 | } else { | ||
| 15875 | ✗ | innobase_table->acquire(); | |
| 15876 | ✗ | ut_ad(innobase_table->is_intrinsic()); | |
| 15877 | } | ||
| 15878 | |||
| 15879 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16491 times.
|
16491 | assert(innobase_table != nullptr); |
| 15880 | |||
| 15881 |
2/2✓ Branch 0 taken 15712 times.
✓ Branch 1 taken 779 times.
|
16491 | if (persist) { |
| 15882 | 15712 | dict_table_autoinc_set_col_pos( | |
| 15883 | 15712 | innobase_table, m_form->found_next_number_field->field_index()); | |
| 15884 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15712 times.
|
15712 | ut_ad(dict_table_has_autoinc_col(innobase_table)); |
| 15885 | } | ||
| 15886 | |||
| 15887 | /* We need to copy the AUTOINC value from the old table if | ||
| 15888 | this is an ALTER|OPTIMIZE TABLE or CREATE INDEX because CREATE INDEX | ||
| 15889 | does a table copy too. If query was one of : | ||
| 15890 | |||
| 15891 | CREATE TABLE ...AUTO_INCREMENT = x; or | ||
| 15892 | ALTER TABLE...AUTO_INCREMENT = x; or | ||
| 15893 | OPTIMIZE TABLE t; or | ||
| 15894 | CREATE INDEX x on t(...); | ||
| 15895 | |||
| 15896 | Find out a table definition from the dictionary and get | ||
| 15897 | the current value of the auto increment field. Set a new | ||
| 15898 | value to the auto increment field if the value is greater | ||
| 15899 | than the maximum value in the column. */ | ||
| 15900 | |||
| 15901 | 16491 | enum_sql_command cmd = static_cast<enum_sql_command>(thd_sql_command(m_thd)); | |
| 15902 | |||
| 15903 |
2/2✓ Branch 0 taken 2102 times.
✓ Branch 1 taken 14389 times.
|
16491 | if (m_create_info->auto_increment_value > 0 && |
| 15904 |
4/4✓ Branch 0 taken 1628 times.
✓ Branch 1 taken 474 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1622 times.
|
2102 | ((m_create_info->used_fields & HA_CREATE_USED_AUTO) || |
| 15905 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
|
6 | cmd == SQLCOM_ALTER_TABLE || cmd == SQLCOM_OPTIMIZE || |
| 15906 | cmd == SQLCOM_CREATE_INDEX)) { | ||
| 15907 | uint64_t auto_inc_value; | ||
| 15908 | |||
| 15909 | 2101 | auto_inc_value = m_create_info->auto_increment_value; | |
| 15910 | |||
| 15911 | 2101 | dict_table_autoinc_lock(innobase_table); | |
| 15912 | 2101 | dict_table_autoinc_initialize(innobase_table, auto_inc_value); | |
| 15913 | 2101 | dict_table_autoinc_unlock(innobase_table); | |
| 15914 | } | ||
| 15915 | |||
| 15916 | 16491 | dd_table_close(innobase_table, nullptr, nullptr, false); | |
| 15917 | } | ||
| 15918 | |||
| 15919 | /** Prepare to create a new table to an InnoDB database. | ||
| 15920 | @param[in] name Table name | ||
| 15921 | @return error number */ | ||
| 15922 | 352410 | int create_table_info_t::prepare_create_table(const char *name) { | |
| 15923 |
1/2✓ Branch 0 taken 352411 times.
✗ Branch 1 not taken.
|
352410 | DBUG_TRACE; |
| 15924 | |||
| 15925 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 352411 times.
|
352411 | ut_ad(m_thd != nullptr); |
| 15926 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 352411 times.
|
352411 | ut_ad(m_form->s->row_type == m_create_info->row_type); |
| 15927 | |||
| 15928 |
2/4✓ Branch 0 taken 352410 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 352410 times.
|
352411 | if (!normalize_table_name(m_table_name, name)) { |
| 15929 | /* purecov: begin inspected */ | ||
| 15930 | ✗ | ut_d(ut_error); | |
| 15931 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 15932 | /* purecov: end */ | ||
| 15933 | } | ||
| 15934 | |||
| 15935 |
1/2✓ Branch 0 taken 352411 times.
✗ Branch 1 not taken.
|
352410 | set_tablespace_type(false); |
| 15936 | |||
| 15937 | /* Validate the create options if innodb_strict_mode is set. | ||
| 15938 | Do not use the regular message for ER_ILLEGAL_HA_CREATE_OPTION | ||
| 15939 | because InnoDB might actually support the option, but not under | ||
| 15940 | the current conditions. The messages revealing the specific | ||
| 15941 | problems are reported inside this function. */ | ||
| 15942 |
3/4✓ Branch 0 taken 352411 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 352243 times.
|
352411 | if (create_options_are_invalid()) { |
| 15943 | 168 | return HA_WRONG_CREATE_OPTION; | |
| 15944 | } | ||
| 15945 | |||
| 15946 | /* Create the table flags and flags2 */ | ||
| 15947 |
6/6✓ Branch 0 taken 336005 times.
✓ Branch 1 taken 16238 times.
✓ Branch 2 taken 335991 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 335992 times.
✓ Branch 5 taken 16250 times.
|
352243 | if (flags() == 0 && flags2() == 0) { |
| 15948 |
3/4✓ Branch 0 taken 335990 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 335989 times.
|
335992 | if (!innobase_table_flags()) { |
| 15949 | 1 | return HA_WRONG_CREATE_OPTION; | |
| 15950 | } | ||
| 15951 | } | ||
| 15952 | |||
| 15953 |
5/8✓ Branch 0 taken 82 times.
✓ Branch 1 taken 352157 times.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 352241 times.
|
352239 | ut_ad(!high_level_read_only || is_intrinsic_temp_table()); |
| 15954 | |||
| 15955 |
1/2✓ Branch 0 taken 352241 times.
✗ Branch 1 not taken.
|
352241 | return parse_table_name(name); |
| 15956 | 352410 | } | |
| 15957 | |||
| 15958 | /** Check a column (name) is a base column for any stored column in the table | ||
| 15959 | @param[in] table TABLE* for the table | ||
| 15960 | @param[in] name column name to check | ||
| 15961 | @return true if this is a base column */ | ||
| 15962 | 1004 | static bool innobase_is_base_s_col(const TABLE *table, const char *name) { | |
| 15963 |
2/2✓ Branch 0 taken 1576 times.
✓ Branch 1 taken 988 times.
|
2564 | for (uint i = 0; i < table->s->fields; ++i) { |
| 15964 | 1576 | const Field *field = table->field[i]; | |
| 15965 | |||
| 15966 |
2/2✓ Branch 0 taken 1558 times.
✓ Branch 1 taken 18 times.
|
1576 | if (!innobase_is_s_fld(field)) { |
| 15967 | 1558 | continue; | |
| 15968 | } | ||
| 15969 | |||
| 15970 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 2 times.
|
25 | for (uint j = 0; j < table->s->fields; ++j) { |
| 15971 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 5 times.
|
23 | if (bitmap_is_set(&field->gcol_info->base_columns_map, j)) { |
| 15972 | 18 | const Field *base_field = table->field[j]; | |
| 15973 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
|
18 | if (innobase_strcasecmp(base_field->field_name, name) == 0) { |
| 15974 | 16 | return (true); | |
| 15975 | } | ||
| 15976 | } | ||
| 15977 | } | ||
| 15978 | } | ||
| 15979 | |||
| 15980 | 988 | return (false); | |
| 15981 | } | ||
| 15982 | |||
| 15983 | /** Check any cascading foreign key columns are base columns | ||
| 15984 | for any stored columns in the table | ||
| 15985 | @param[in] dd_table dd::Table for the table | ||
| 15986 | @param[in] table TABLE* for the table | ||
| 15987 | @return DB_NO_FK_ON_S_BASE_COL if found or DB_SUCCESS */ | ||
| 15988 | 237262 | static dberr_t innobase_check_fk_base_col(const dd::Table *dd_table, | |
| 15989 | const TABLE *table) { | ||
| 15990 |
6/10✓ Branch 0 taken 237264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 237264 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 237264 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19075 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19075 times.
✓ Branch 9 taken 237247 times.
|
256321 | for (const dd::Foreign_key *key : dd_table->foreign_keys()) { |
| 15991 | 19075 | bool upd_cascade = false; | |
| 15992 | 19075 | bool del_cascade = false; | |
| 15993 | |||
| 15994 |
3/5✓ Branch 0 taken 19075 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 819 times.
✓ Branch 3 taken 18256 times.
✗ Branch 4 not taken.
|
19075 | switch (key->update_rule()) { |
| 15995 | 819 | case dd::Foreign_key::RULE_CASCADE: | |
| 15996 | case dd::Foreign_key::RULE_SET_NULL: | ||
| 15997 | 819 | upd_cascade = true; | |
| 15998 | 819 | break; | |
| 15999 | 18256 | case dd::Foreign_key::RULE_NO_ACTION: | |
| 16000 | case dd::Foreign_key::RULE_RESTRICT: | ||
| 16001 | case dd::Foreign_key::RULE_SET_DEFAULT: | ||
| 16002 | 18256 | break; | |
| 16003 | } | ||
| 16004 | |||
| 16005 |
3/5✓ Branch 0 taken 19075 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 215 times.
✓ Branch 3 taken 18860 times.
✗ Branch 4 not taken.
|
19075 | switch (key->delete_rule()) { |
| 16006 | 215 | case dd::Foreign_key::RULE_CASCADE: | |
| 16007 | case dd::Foreign_key::RULE_SET_NULL: | ||
| 16008 | 215 | del_cascade = true; | |
| 16009 | 215 | break; | |
| 16010 | 18860 | case dd::Foreign_key::RULE_NO_ACTION: | |
| 16011 | case dd::Foreign_key::RULE_RESTRICT: | ||
| 16012 | case dd::Foreign_key::RULE_SET_DEFAULT: | ||
| 16013 | 18860 | break; | |
| 16014 | } | ||
| 16015 | |||
| 16016 |
4/4✓ Branch 0 taken 18256 times.
✓ Branch 1 taken 819 times.
✓ Branch 2 taken 18081 times.
✓ Branch 3 taken 175 times.
|
19075 | if (!upd_cascade && !del_cascade) { |
| 16017 | 18081 | continue; | |
| 16018 | } | ||
| 16019 | |||
| 16020 |
6/10✓ Branch 0 taken 994 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 994 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 994 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1004 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1004 times.
✓ Branch 9 taken 978 times.
|
1982 | for (const dd::Foreign_key_element *key_e : key->elements()) { |
| 16021 |
3/6✓ Branch 0 taken 1004 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1004 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1004 times.
✗ Branch 5 not taken.
|
1004 | dd::String_type col_name = key_e->column().name(); |
| 16022 | |||
| 16023 |
3/4✓ Branch 0 taken 1004 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 988 times.
|
1004 | if (innobase_is_base_s_col(table, col_name.c_str())) { |
| 16024 | 16 | return (DB_NO_FK_ON_S_BASE_COL); | |
| 16025 | } | ||
| 16026 |
2/2✓ Branch 0 taken 988 times.
✓ Branch 1 taken 16 times.
|
1004 | } |
| 16027 | } | ||
| 16028 | 237247 | return (DB_SUCCESS); | |
| 16029 | } | ||
| 16030 | |||
| 16031 | /** Create the internal innodb table. | ||
| 16032 | @param[in] dd_table dd::Table or nullptr for intrinsic table | ||
| 16033 | @param[in] old_part_table dd::Table from an old partition for partitioned | ||
| 16034 | table, NULL otherwise. | ||
| 16035 | @return 0 or error number */ | ||
| 16036 | 348239 | int create_table_info_t::create_table(const dd::Table *dd_table, | |
| 16037 | const dd::Table *old_part_table) { | ||
| 16038 | int error; | ||
| 16039 | uint primary_key_no; | ||
| 16040 | uint i; | ||
| 16041 | const char *stmt; | ||
| 16042 | size_t stmt_len; | ||
| 16043 | |||
| 16044 |
1/2✓ Branch 0 taken 348241 times.
✗ Branch 1 not taken.
|
348239 | DBUG_TRACE; |
| 16045 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 348241 times.
|
348241 | assert(m_form->s->keys <= MAX_KEY); |
| 16046 | |||
| 16047 | /* Check if dd table has hidden fts doc id index. | ||
| 16048 | Note: in case of TRUNCATE a fulltext table with | ||
| 16049 | hidden doc id index. */ | ||
| 16050 |
2/2✓ Branch 0 taken 237262 times.
✓ Branch 1 taken 110979 times.
|
348241 | if (dd_table != nullptr) { |
| 16051 |
1/2✓ Branch 0 taken 237263 times.
✗ Branch 1 not taken.
|
237262 | dberr_t err = innobase_check_fk_base_col(dd_table, m_form); |
| 16052 | |||
| 16053 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 237247 times.
|
237263 | if (err != DB_SUCCESS) { |
| 16054 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | error = convert_error_code_to_mysql(err, m_flags, nullptr); |
| 16055 | |||
| 16056 | 16 | return error; | |
| 16057 | } | ||
| 16058 | |||
| 16059 |
6/10✓ Branch 0 taken 237248 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 237248 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 237248 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 309738 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 309736 times.
✓ Branch 9 taken 237248 times.
|
546983 | for (auto index : dd_table->indexes()) { |
| 16060 |
2/4✓ Branch 0 taken 309737 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 309736 times.
✗ Branch 3 not taken.
|
309738 | if (my_strcasecmp(system_charset_info, index->name().c_str(), |
| 16061 |
4/4✓ Branch 0 taken 470 times.
✓ Branch 1 taken 309266 times.
✓ Branch 2 taken 463 times.
✓ Branch 3 taken 309273 times.
|
310206 | FTS_DOC_ID_INDEX_NAME) == 0 && |
| 16062 |
3/4✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 463 times.
✓ Branch 3 taken 7 times.
|
470 | index->is_hidden()) { |
| 16063 | 463 | m_flags2 |= DICT_TF2_FTS_ADD_DOC_ID; | |
| 16064 | } | ||
| 16065 | } | ||
| 16066 | } | ||
| 16067 | |||
| 16068 | /* Look for a primary key */ | ||
| 16069 | 348227 | primary_key_no = m_form->s->primary_key; | |
| 16070 | |||
| 16071 | /* Our function innobase_get_mysql_key_number_for_index assumes | ||
| 16072 | the primary key is always number 0, if it exists */ | ||
| 16073 |
4/6✓ Branch 0 taken 105729 times.
✓ Branch 1 taken 242498 times.
✓ Branch 2 taken 105729 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 348225 times.
|
348227 | ut_a(primary_key_no == MAX_KEY || primary_key_no == 0); |
| 16074 | |||
| 16075 |
1/2✓ Branch 0 taken 348184 times.
✗ Branch 1 not taken.
|
348225 | error = create_table_def(dd_table, old_part_table); |
| 16076 |
2/2✓ Branch 0 taken 73 times.
✓ Branch 1 taken 348111 times.
|
348184 | if (error) { |
| 16077 | 73 | return error; | |
| 16078 | } | ||
| 16079 | |||
| 16080 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 348111 times.
|
348111 | ut_ad(m_table != nullptr); |
| 16081 | |||
| 16082 | /* Create the keys */ | ||
| 16083 | |||
| 16084 |
4/4✓ Branch 0 taken 118816 times.
✓ Branch 1 taken 229295 times.
✓ Branch 2 taken 13149 times.
✓ Branch 3 taken 105667 times.
|
348111 | if (m_form->s->keys == 0 || primary_key_no == MAX_KEY) { |
| 16085 | /* Create an index which is used as the clustered index; | ||
| 16086 | order the rows by their row id which is internally generated | ||
| 16087 | by InnoDB */ | ||
| 16088 | |||
| 16089 | error = | ||
| 16090 |
1/2✓ Branch 0 taken 242444 times.
✗ Branch 1 not taken.
|
242444 | create_clustered_index_when_no_primary(m_trx, m_flags, m_table_name); |
| 16091 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 242431 times.
|
242444 | if (error) { |
| 16092 | 13 | return error; | |
| 16093 | } | ||
| 16094 | } | ||
| 16095 | |||
| 16096 |
2/2✓ Branch 0 taken 105667 times.
✓ Branch 1 taken 242431 times.
|
348098 | if (primary_key_no != MAX_KEY) { |
| 16097 | /* In InnoDB the clustered index must always be created | ||
| 16098 | first */ | ||
| 16099 |
1/2✓ Branch 0 taken 105625 times.
✗ Branch 1 not taken.
|
105667 | error = create_index(m_trx, m_form, m_flags, m_table_name, primary_key_no, |
| 16100 | dd_table); | ||
| 16101 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 105615 times.
|
105625 | if (error) { |
| 16102 | 10 | return error; | |
| 16103 | } | ||
| 16104 | } | ||
| 16105 | |||
| 16106 | /* Create the ancillary tables that are common to all FTS indexes on | ||
| 16107 | this table. */ | ||
| 16108 |
2/2✓ Branch 0 taken 470 times.
✓ Branch 1 taken 347576 times.
|
348046 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) { |
| 16109 | fts_doc_id_index_enum ret; | ||
| 16110 | |||
| 16111 | /* Check whether there already exists FTS_DOC_ID_INDEX */ | ||
| 16112 | 940 | ret = innobase_fts_check_doc_id_index_in_def(m_form->s->keys, | |
| 16113 |
1/2✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
|
470 | m_form->key_info); |
| 16114 | |||
| 16115 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
✗ Branch 2 not taken.
|
470 | switch (ret) { |
| 16116 | ✗ | case FTS_INCORRECT_DOC_ID_INDEX: | |
| 16117 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 16118 | ER_WRONG_NAME_FOR_INDEX, | ||
| 16119 | " InnoDB: Index name %s is reserved" | ||
| 16120 | " for the unique index on" | ||
| 16121 | " FTS_DOC_ID column for FTS" | ||
| 16122 | " Document ID indexing" | ||
| 16123 | " on table %s. Please check" | ||
| 16124 | " the index definition to" | ||
| 16125 | " make sure it is of correct" | ||
| 16126 | " type\n", | ||
| 16127 | ✗ | FTS_DOC_ID_INDEX_NAME, m_table->name.m_name); | |
| 16128 | |||
| 16129 | ✗ | if (m_table->fts) { | |
| 16130 | ✗ | fts_free(m_table); | |
| 16131 | } | ||
| 16132 | |||
| 16133 | ✗ | my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), FTS_DOC_ID_INDEX_NAME); | |
| 16134 | ✗ | error = -1; | |
| 16135 | ✗ | return error; | |
| 16136 | 470 | case FTS_EXIST_DOC_ID_INDEX: | |
| 16137 | case FTS_NOT_EXIST_DOC_ID_INDEX: | ||
| 16138 | 470 | break; | |
| 16139 | } | ||
| 16140 | |||
| 16141 |
1/2✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
|
470 | dberr_t err = fts_create_common_tables(m_trx, m_table, m_table_name, |
| 16142 | (ret == FTS_EXIST_DOC_ID_INDEX)); | ||
| 16143 | |||
| 16144 |
1/2✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
|
470 | error = convert_error_code_to_mysql(err, 0, nullptr); |
| 16145 | |||
| 16146 | 470 | DICT_TF2_FLAG_UNSET(m_table, DICT_TF2_FTS_ADD_DOC_ID); | |
| 16147 | |||
| 16148 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 466 times.
|
470 | if (error) { |
| 16149 | 4 | return error; | |
| 16150 | } | ||
| 16151 | } | ||
| 16152 | |||
| 16153 |
2/2✓ Branch 0 taken 179512 times.
✓ Branch 1 taken 347993 times.
|
527505 | for (i = 0; i < m_form->s->keys; i++) { |
| 16154 |
2/2✓ Branch 0 taken 73899 times.
✓ Branch 1 taken 105613 times.
|
179512 | if (i != primary_key_no) { |
| 16155 |
1/2✓ Branch 0 taken 73858 times.
✗ Branch 1 not taken.
|
73899 | error = create_index(m_trx, m_form, m_flags, m_table_name, i, dd_table); |
| 16156 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 73850 times.
|
73858 | if (error) { |
| 16157 | 8 | return error; | |
| 16158 | } | ||
| 16159 | } | ||
| 16160 | } | ||
| 16161 | |||
| 16162 |
1/2✓ Branch 0 taken 347993 times.
✗ Branch 1 not taken.
|
347993 | initialize_autoinc(); |
| 16163 | |||
| 16164 | /* Cache all the FTS indexes on this table in the FTS specific | ||
| 16165 | structure. They are used for FTS indexed column update handling. */ | ||
| 16166 |
2/2✓ Branch 0 taken 457 times.
✓ Branch 1 taken 347536 times.
|
347993 | if (m_flags2 & DICT_TF2_FTS) { |
| 16167 | 457 | fts_t *fts = m_table->fts; | |
| 16168 | |||
| 16169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
|
457 | ut_a(fts != nullptr); |
| 16170 | |||
| 16171 |
1/2✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
|
457 | dict_table_get_all_fts_indexes(m_table, fts->indexes); |
| 16172 | } | ||
| 16173 | |||
| 16174 |
1/2✓ Branch 0 taken 347993 times.
✗ Branch 1 not taken.
|
347993 | stmt = innobase_get_stmt_unsafe(m_thd, &stmt_len); |
| 16175 | |||
| 16176 |
1/2✓ Branch 0 taken 347993 times.
✗ Branch 1 not taken.
|
347993 | innodb_session_t *&priv = thd_to_innodb_session(m_trx->mysql_thd); |
| 16177 |
1/2✓ Branch 0 taken 347993 times.
✗ Branch 1 not taken.
|
347993 | dict_table_t *handler = priv->lookup_table_handler(m_table_name); |
| 16178 | |||
| 16179 |
5/8✓ Branch 0 taken 110974 times.
✓ Branch 1 taken 237019 times.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 110974 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 347993 times.
|
347993 | ut_ad(handler == nullptr || handler->is_intrinsic()); |
| 16180 |
5/8✓ Branch 0 taken 110974 times.
✓ Branch 1 taken 237019 times.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 110974 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 347993 times.
|
347993 | ut_ad(handler == nullptr || is_intrinsic_temp_table()); |
| 16181 | |||
| 16182 | /* There is no concept of foreign key for intrinsic tables. */ | ||
| 16183 |
4/6✓ Branch 0 taken 237019 times.
✓ Branch 1 taken 110974 times.
✓ Branch 2 taken 237019 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 237019 times.
✗ Branch 5 not taken.
|
347993 | if (handler == nullptr && stmt != nullptr && dd_table != nullptr |
| 16184 | /* FIXME: NewDD: WL#6049 should add a new call to check if a table | ||
| 16185 | is a parent table of any FK. If the table is not child table, nor | ||
| 16186 | parent table, then it can skip the check: | ||
| 16187 | dd_table->foreign_keys().empty() && | ||
| 16188 | dd_table->referenced_keys().empty() */ | ||
| 16189 | ) { | ||
| 16190 | 237019 | dberr_t err = DB_SUCCESS; | |
| 16191 | |||
| 16192 |
1/2✓ Branch 0 taken 237019 times.
✗ Branch 1 not taken.
|
237019 | dict_sys_mutex_enter(); |
| 16193 |
1/2✓ Branch 0 taken 237019 times.
✗ Branch 1 not taken.
|
237019 | err = row_table_load_foreign_constraints(m_trx, m_table_name, dd_table); |
| 16194 |
1/2✓ Branch 0 taken 237019 times.
✗ Branch 1 not taken.
|
237019 | dict_sys_mutex_exit(); |
| 16195 | |||
| 16196 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 237019 times.
|
237019 | switch (err) { |
| 16197 | ✗ | case DB_PARENT_NO_INDEX: | |
| 16198 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 16199 | HA_ERR_CANNOT_ADD_FOREIGN, | ||
| 16200 | "Create table '%s' with foreign key constraint" | ||
| 16201 | " failed. There is no index in the referenced" | ||
| 16202 | " table where the referenced columns appear" | ||
| 16203 | " as the first columns.\n", | ||
| 16204 | m_table_name); | ||
| 16205 | ✗ | break; | |
| 16206 | |||
| 16207 | ✗ | case DB_CHILD_NO_INDEX: | |
| 16208 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 16209 | HA_ERR_CANNOT_ADD_FOREIGN, | ||
| 16210 | "Create table '%s' with foreign key constraint" | ||
| 16211 | " failed. There is no index in the referencing" | ||
| 16212 | " table where referencing columns appear" | ||
| 16213 | " as the first columns.\n", | ||
| 16214 | m_table_name); | ||
| 16215 | ✗ | break; | |
| 16216 | ✗ | case DB_NO_FK_ON_S_BASE_COL: | |
| 16217 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 16218 | HA_ERR_CANNOT_ADD_FOREIGN, | ||
| 16219 | "Create table '%s' with foreign key constraint" | ||
| 16220 | " failed. Cannot add foreign key constraint" | ||
| 16221 | " placed on the base column of stored" | ||
| 16222 | " column.\n", | ||
| 16223 | m_table_name); | ||
| 16224 | ✗ | break; | |
| 16225 | 237019 | default: | |
| 16226 | 237019 | break; | |
| 16227 | } | ||
| 16228 | |||
| 16229 |
1/2✓ Branch 0 taken 237019 times.
✗ Branch 1 not taken.
|
237019 | error = convert_error_code_to_mysql(err, m_flags, nullptr); |
| 16230 | |||
| 16231 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 237017 times.
|
237019 | if (error) { |
| 16232 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (handler != nullptr) { |
| 16233 | ✗ | priv->unregister_table_handler(m_table_name); | |
| 16234 | } | ||
| 16235 | 2 | return error; | |
| 16236 | } | ||
| 16237 | } | ||
| 16238 | |||
| 16239 | 347991 | return 0; | |
| 16240 | 348117 | } | |
| 16241 | |||
| 16242 | /** Update a new table in an InnoDB database. | ||
| 16243 | @return error number */ | ||
| 16244 | 347991 | int create_table_info_t::create_table_update_dict() { | |
| 16245 |
1/2✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
|
347991 | DBUG_TRACE; |
| 16246 | |||
| 16247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 347991 times.
|
347991 | assert(m_table != nullptr); |
| 16248 | |||
| 16249 | #ifdef UNIV_DEBUG | ||
| 16250 |
3/4✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110974 times.
✓ Branch 3 taken 237017 times.
|
347991 | if (m_table->is_intrinsic()) { |
| 16251 | dict_table_t *innobase_table = | ||
| 16252 |
2/4✓ Branch 0 taken 110974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
|
110974 | thd_to_innodb_session(m_thd)->lookup_table_handler(m_table_name); |
| 16253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 110974 times.
|
110974 | ut_ad(m_table == innobase_table); |
| 16254 | } | ||
| 16255 | #endif /* UNIV_DEBUG */ | ||
| 16256 | |||
| 16257 | /* Temp table must be uncompressed and reside in tmp tablespace. */ | ||
| 16258 |
2/4✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 347991 times.
|
347991 | ut_ad(!dict_table_is_compressed_temporary(m_table)); |
| 16259 |
2/2✓ Branch 0 taken 462 times.
✓ Branch 1 taken 347529 times.
|
347991 | if (m_table->fts != nullptr) { |
| 16260 |
1/2✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
|
462 | if (m_table->fts_doc_id_index == nullptr) { |
| 16261 | 924 | m_table->fts_doc_id_index = | |
| 16262 |
1/2✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
|
462 | dict_table_get_index_on_name(m_table, FTS_DOC_ID_INDEX_NAME); |
| 16263 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
|
462 | assert(m_table->fts_doc_id_index != nullptr); |
| 16264 | } else { | ||
| 16265 | ✗ | assert(m_table->fts_doc_id_index == | |
| 16266 | dict_table_get_index_on_name(m_table, FTS_DOC_ID_INDEX_NAME)); | ||
| 16267 | } | ||
| 16268 | } | ||
| 16269 | |||
| 16270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 347991 times.
|
347991 | assert((m_table->fts == nullptr) == (m_table->fts_doc_id_index == nullptr)); |
| 16271 | |||
| 16272 |
1/2✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
|
347991 | innobase_copy_frm_flags_from_create_info(m_table, m_create_info); |
| 16273 | |||
| 16274 |
1/2✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
|
347991 | dict_stats_update(m_table, DICT_STATS_EMPTY_TABLE); |
| 16275 | |||
| 16276 | /* Since no dict_table_close(), deinitialize it explicitly. */ | ||
| 16277 |
1/2✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
|
347991 | dict_stats_deinit(m_table); |
| 16278 | |||
| 16279 | /* Load server stopword into FTS cache */ | ||
| 16280 |
2/2✓ Branch 0 taken 457 times.
✓ Branch 1 taken 347534 times.
|
347991 | if (m_flags2 & DICT_TF2_FTS) { |
| 16281 |
2/4✓ Branch 0 taken 457 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 457 times.
|
457 | if (!innobase_fts_load_stopword(m_table, nullptr, m_thd)) { |
| 16282 | ✗ | return -1; | |
| 16283 | } | ||
| 16284 | } | ||
| 16285 | |||
| 16286 |
1/2✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
|
347991 | innobase_parse_hint_from_comment(m_thd, m_table, m_form->s); |
| 16287 | 347991 | return 0; | |
| 16288 | 347991 | } | |
| 16289 | |||
| 16290 | /** Update the global data dictionary. | ||
| 16291 | @param[in] dd_table dd::Table or dd::Partition | ||
| 16292 | @retval 0 On success | ||
| 16293 | @retval error number On failure */ | ||
| 16294 | template <typename Table> | ||
| 16295 | 695982 | int create_table_info_t::create_table_update_global_dd(Table *dd_table) { | |
| 16296 |
1/2✓ Branch 0 taken 347991 times.
✗ Branch 1 not taken.
|
695982 | DBUG_TRACE; |
| 16297 | |||
| 16298 |
4/4✓ Branch 0 taken 237017 times.
✓ Branch 1 taken 110974 times.
✓ Branch 2 taken 42541 times.
✓ Branch 3 taken 194476 times.
|
695982 | if (dd_table == nullptr || (m_flags2 & DICT_TF2_TEMPORARY)) { |
| 16299 | /* No need to fill in metadata for all temporary tables. | ||
| 16300 | The Table object for temporary table is either NULL or | ||
| 16301 | a fake one, whose metadata would not be written back later */ | ||
| 16302 | 307030 | return 0; | |
| 16303 | } | ||
| 16304 | |||
| 16305 |
2/2✓ Branch 0 taken 15712 times.
✓ Branch 1 taken 178764 times.
|
388952 | if (m_form->found_next_number_field != nullptr) { |
| 16306 |
1/2✓ Branch 0 taken 15712 times.
✗ Branch 1 not taken.
|
31424 | dd_set_autoinc(dd_table->se_private_data(), |
| 16307 |
1/2✓ Branch 0 taken 15712 times.
✗ Branch 1 not taken.
|
31424 | m_create_info->auto_increment_value); |
| 16308 | } | ||
| 16309 | |||
| 16310 |
1/2✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
|
388952 | dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd); |
| 16311 |
1/2✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
|
388952 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 16312 | |||
| 16313 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 194476 times.
|
388952 | ut_ad(m_table != nullptr); |
| 16314 |
2/4✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 194476 times.
|
388952 | ut_ad(!m_table->is_temporary()); |
| 16315 | |||
| 16316 |
1/2✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
|
388952 | bool file_per_table = dict_table_is_file_per_table(m_table); |
| 16317 | 388952 | dd::Object_id dd_space_id = dd::INVALID_OBJECT_ID; | |
| 16318 | 388952 | bool is_dd_table = m_table->space == dict_sys_t::s_dict_space_id; | |
| 16319 | |||
| 16320 |
2/2✓ Branch 0 taken 23004 times.
✓ Branch 1 taken 171472 times.
|
388952 | if (is_dd_table) { |
| 16321 | 46008 | dd_space_id = dict_sys_t::s_dd_dict_space_id; | |
| 16322 |
2/2✓ Branch 0 taken 4736 times.
✓ Branch 1 taken 166736 times.
|
342944 | } else if (m_table->space == TRX_SYS_SPACE) { |
| 16323 | 9472 | dd_space_id = dict_sys_t::s_dd_sys_space_id; | |
| 16324 |
2/2✓ Branch 0 taken 165597 times.
✓ Branch 1 taken 1139 times.
|
333472 | } else if (file_per_table) { |
| 16325 |
1/2✓ Branch 0 taken 165597 times.
✗ Branch 1 not taken.
|
331194 | char *filename = fil_space_get_first_path(m_table->space); |
| 16326 | |||
| 16327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 165597 times.
|
331194 | if (dd_create_implicit_tablespace(client, m_table->space, |
| 16328 |
1/2✓ Branch 0 taken 165597 times.
✗ Branch 1 not taken.
|
331194 | m_table->name.m_name, filename, false, |
| 16329 | dd_space_id)) { | ||
| 16330 | ✗ | ut::free(filename); | |
| 16331 | ✗ | return HA_ERR_GENERIC; | |
| 16332 | } | ||
| 16333 | |||
| 16334 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 165597 times.
|
331194 | ut_ad(dd_space_id != dd::INVALID_OBJECT_ID); |
| 16335 | 331194 | ut::free(filename); | |
| 16336 | } else { | ||
| 16337 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1139 times.
|
2278 | ut_ad(DICT_TF_HAS_SHARED_SPACE(m_table->flags)); |
| 16338 | |||
| 16339 |
1/2✓ Branch 0 taken 1139 times.
✗ Branch 1 not taken.
|
2278 | dd_space_id = dd_get_space_id(*dd_table); |
| 16340 | |||
| 16341 | 2278 | const dd::Tablespace *index_space = nullptr; | |
| 16342 |
2/4✓ Branch 0 taken 1139 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1139 times.
|
2278 | if (client->acquire<dd::Tablespace>(dd_space_id, &index_space)) { |
| 16343 | ✗ | return HA_ERR_GENERIC; | |
| 16344 | } | ||
| 16345 | |||
| 16346 |
2/4✓ Branch 0 taken 1139 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1139 times.
|
2278 | DBUG_EXECUTE_IF("create_table_update_dd_fail", index_space = nullptr;); |
| 16347 | |||
| 16348 | uint32_t id; | ||
| 16349 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1139 times.
|
2278 | if (index_space == nullptr) { |
| 16350 | ✗ | my_error(ER_TABLESPACE_MISSING, MYF(0), m_table->name.m_name); | |
| 16351 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 16352 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1139 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2278 | } else if (index_space->se_private_data().get( |
| 16353 |
5/10✓ Branch 0 taken 1139 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1139 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1139 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1139 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1139 times.
✗ Branch 9 not taken.
|
4556 | dd_space_key_strings[DD_SPACE_ID], &id) || |
| 16354 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1139 times.
|
2278 | id != m_table->space) { |
| 16355 | ✗ | ut_ad(!"missing or incorrect tablespace id"); | |
| 16356 | ✗ | return HA_ERR_GENERIC; | |
| 16357 | } | ||
| 16358 | } | ||
| 16359 | |||
| 16360 | 388952 | m_table->dd_space_id = dd_space_id; | |
| 16361 | |||
| 16362 |
1/2✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
|
388952 | dd_set_table_options(dd_table, m_table); |
| 16363 | |||
| 16364 |
1/2✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
|
388952 | dd_write_table(dd_space_id, dd_table, m_table); |
| 16365 | |||
| 16366 |
2/2✓ Branch 0 taken 462 times.
✓ Branch 1 taken 194014 times.
|
388952 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) { |
| 16367 |
1/2✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
|
924 | ut_d(bool ret =) fts_create_common_dd_tables(m_table); |
| 16368 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
|
924 | ut_ad(ret); |
| 16369 |
1/2✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
|
924 | fts_create_index_dd_tables(m_table); |
| 16370 | } | ||
| 16371 | |||
| 16372 |
2/4✓ Branch 0 taken 194476 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 194476 times.
|
388952 | ut_ad(dd_table_match(m_table, dd_table)); |
| 16373 | |||
| 16374 | 388952 | return 0; | |
| 16375 | 695982 | } | |
| 16376 | |||
| 16377 | template int create_table_info_t::create_table_update_global_dd<dd::Table>( | ||
| 16378 | dd::Table *); | ||
| 16379 | |||
| 16380 | template int create_table_info_t::create_table_update_global_dd<dd::Partition>( | ||
| 16381 | dd::Partition *); | ||
| 16382 | |||
| 16383 | template <typename Table> | ||
| 16384 | 642126 | int innobase_basic_ddl::create_impl(THD *thd, const char *name, TABLE *form, | |
| 16385 | HA_CREATE_INFO *create_info, Table *dd_tab, | ||
| 16386 | bool file_per_table, bool evictable, | ||
| 16387 | bool skip_strict, uint32_t old_flags, | ||
| 16388 | uint32_t old_flags2, | ||
| 16389 | const dd::Table *old_part_table) { | ||
| 16390 | 642126 | char norm_name[FN_REFLEN] = {'\0'}; /* {database}/{tablename} */ | |
| 16391 | 642126 | char remote_path[FN_REFLEN] = {'\0'}; /* Absolute path of table */ | |
| 16392 | 642126 | char tablespace[NAME_LEN] = {'\0'}; /* Tablespace name identifier */ | |
| 16393 | trx_t *trx; | ||
| 16394 | |||
| 16395 |
2/2✓ Branch 0 taken 87 times.
✓ Branch 1 taken 320976 times.
|
642126 | if (high_level_read_only && |
| 16396 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 82 times.
|
174 | !(create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE)) { |
| 16397 | 10 | return HA_ERR_INNODB_READ_ONLY; | |
| 16398 | } | ||
| 16399 | |||
| 16400 | /* Get the transaction associated with the current thd, or create one | ||
| 16401 | if not yet created */ | ||
| 16402 |
1/2✓ Branch 0 taken 321058 times.
✗ Branch 1 not taken.
|
642116 | trx = check_trx_exists(thd); |
| 16403 | |||
| 16404 |
2/2✓ Branch 0 taken 167496 times.
✓ Branch 1 taken 153562 times.
|
642116 | if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { |
| 16405 |
1/2✓ Branch 0 taken 167496 times.
✗ Branch 1 not taken.
|
334992 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 16406 | } | ||
| 16407 | |||
| 16408 |
1/2✓ Branch 0 taken 321057 times.
✗ Branch 1 not taken.
|
642116 | create_table_info_t info(thd, form, create_info, norm_name, remote_path, |
| 16409 | tablespace, file_per_table, skip_strict, old_flags, | ||
| 16410 | old_flags2, false); | ||
| 16411 | |||
| 16412 | /* Initialize the object. */ | ||
| 16413 |
1/2✓ Branch 0 taken 321058 times.
✗ Branch 1 not taken.
|
642114 | int error = info.initialize(); |
| 16414 | |||
| 16415 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 321048 times.
|
642116 | if (error != 0) { |
| 16416 | 20 | return (error); | |
| 16417 | } | ||
| 16418 | |||
| 16419 | /* Prepare for create and validate options. */ | ||
| 16420 |
1/2✓ Branch 0 taken 321048 times.
✗ Branch 1 not taken.
|
642096 | error = info.prepare_create_table(name); |
| 16421 | |||
| 16422 |
2/2✓ Branch 0 taken 157 times.
✓ Branch 1 taken 320891 times.
|
642096 | if (error != 0) { |
| 16423 | 314 | return (error); | |
| 16424 | } | ||
| 16425 | |||
| 16426 |
5/7✓ Branch 0 taken 209912 times.
✓ Branch 1 taken 110979 times.
✓ Branch 2 taken 7363 times.
✓ Branch 3 taken 313506 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7288 times.
✗ Branch 6 not taken.
|
641782 | error = info.create_table(dd_tab != nullptr ? &dd_tab->table() : nullptr, |
| 16427 | old_part_table); | ||
| 16428 |
2/2✓ Branch 0 taken 126 times.
✓ Branch 1 taken 320668 times.
|
641588 | if (error) { |
| 16429 | 252 | goto cleanup; | |
| 16430 | } | ||
| 16431 | |||
| 16432 |
1/2✓ Branch 0 taken 320668 times.
✗ Branch 1 not taken.
|
641336 | error = info.create_table_update_global_dd(dd_tab); |
| 16433 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 320668 times.
|
641336 | if (error) { |
| 16434 | ✗ | goto cleanup; | |
| 16435 | } | ||
| 16436 | |||
| 16437 |
1/2✓ Branch 0 taken 320668 times.
✗ Branch 1 not taken.
|
641336 | error = info.create_table_update_dict(); |
| 16438 | |||
| 16439 |
9/10✓ Branch 0 taken 302570 times.
✓ Branch 1 taken 18098 times.
✓ Branch 2 taken 260076 times.
✓ Branch 3 taken 42494 times.
✓ Branch 4 taken 260076 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 149102 times.
✓ Branch 7 taken 110974 times.
✓ Branch 8 taken 149102 times.
✓ Branch 9 taken 171566 times.
|
641336 | if (evictable && !(info.is_temp_table() || info.is_intrinsic_temp_table())) { |
| 16440 |
1/2✓ Branch 0 taken 149102 times.
✗ Branch 1 not taken.
|
298204 | info.detach(); |
| 16441 | } | ||
| 16442 | |||
| 16443 | 641336 | return (error); | |
| 16444 | |||
| 16445 | 252 | cleanup: | |
| 16446 |
7/8✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 123 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 119 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 122 times.
|
252 | if (!info.is_intrinsic_temp_table() && info.is_temp_table()) { |
| 16447 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
8 | dict_sys_mutex_enter(); |
| 16448 | |||
| 16449 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
8 | dict_table_t *table = dict_table_check_if_in_cache_low(norm_name); |
| 16450 | |||
| 16451 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
8 | if (table != nullptr) { |
| 16452 |
3/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
8 | for (dict_index_t *index = table->first_index(); index != nullptr; |
| 16453 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | index = index->next()) { |
| 16454 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
4 | ut_ad(index->space == table->space); |
| 16455 | 4 | page_no_t root = index->page; | |
| 16456 | 4 | index->page = FIL_NULL; | |
| 16457 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | dict_drop_temporary_table_index(index, root); |
| 16458 | } | ||
| 16459 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | dict_table_remove_from_cache(table); |
| 16460 | } | ||
| 16461 | |||
| 16462 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
8 | dict_sys_mutex_exit(); |
| 16463 | } else { | ||
| 16464 | dict_table_t *intrinsic_table = | ||
| 16465 |
2/4✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 122 times.
✗ Branch 3 not taken.
|
244 | thd_to_innodb_session(thd)->lookup_table_handler(info.table_name()); |
| 16466 | |||
| 16467 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 121 times.
|
244 | if (intrinsic_table != nullptr) { |
| 16468 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | thd_to_innodb_session(thd)->unregister_table_handler(info.table_name()); |
| 16469 | |||
| 16470 | ✗ | for (;;) { | |
| 16471 | dict_index_t *index; | ||
| 16472 | 2 | index = UT_LIST_GET_FIRST(intrinsic_table->indexes); | |
| 16473 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | if (index == nullptr) { |
| 16474 | 2 | break; | |
| 16475 | } | ||
| 16476 | ✗ | rw_lock_free(&index->lock); | |
| 16477 | ✗ | UT_LIST_REMOVE(intrinsic_table->indexes, index); | |
| 16478 | ✗ | dict_mem_index_free(index); | |
| 16479 | ✗ | index = nullptr; | |
| 16480 | } | ||
| 16481 | |||
| 16482 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | dict_mem_table_free(intrinsic_table); |
| 16483 | 2 | intrinsic_table = nullptr; | |
| 16484 | } | ||
| 16485 | } | ||
| 16486 | |||
| 16487 | 252 | return (error); | |
| 16488 | } | ||
| 16489 | |||
| 16490 | template int innobase_basic_ddl::create_impl<dd::Table>( | ||
| 16491 | THD *, const char *, TABLE *, HA_CREATE_INFO *, dd::Table *, bool, bool, | ||
| 16492 | bool, uint32_t, uint32_t, const dd::Table *); | ||
| 16493 | |||
| 16494 | template int innobase_basic_ddl::create_impl<dd::Partition>( | ||
| 16495 | THD *, const char *, TABLE *, HA_CREATE_INFO *, dd::Partition *, bool, bool, | ||
| 16496 | bool, uint32_t, uint32_t, const dd::Table *); | ||
| 16497 | |||
| 16498 | template <typename Table> | ||
| 16499 | 635534 | int innobase_basic_ddl::delete_impl(THD *thd, const char *name, | |
| 16500 | const Table *dd_tab, const TABLE *td) { | ||
| 16501 | 635534 | dberr_t error = DB_SUCCESS; | |
| 16502 | char norm_name[FN_REFLEN]; | ||
| 16503 | |||
| 16504 |
2/6✓ Branch 0 taken 317768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 317768 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
635534 | DBUG_EXECUTE_IF("test_normalize_table_name", test_normalize_table_name();); |
| 16505 |
4/6✓ Branch 0 taken 317769 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 317768 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
635536 | DBUG_EXECUTE_IF("test_ut_format_name", test_ut_format_name();); |
| 16506 | |||
| 16507 | /* Strangely, MySQL passes the table name without the '.frm' | ||
| 16508 | extension, in contrast to ::create */ | ||
| 16509 |
2/4✓ Branch 0 taken 317767 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 317767 times.
|
635538 | if (!normalize_table_name(norm_name, name)) { |
| 16510 | /* purecov: begin inspected */ | ||
| 16511 | ✗ | ut_d(ut_error); | |
| 16512 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 16513 | /* purecov: end */ | ||
| 16514 | } | ||
| 16515 | |||
| 16516 |
1/2✓ Branch 0 taken 317771 times.
✗ Branch 1 not taken.
|
635534 | innodb_session_t *&priv = thd_to_innodb_session(thd); |
| 16517 |
1/2✓ Branch 0 taken 317771 times.
✗ Branch 1 not taken.
|
635542 | dict_table_t *handler = priv->lookup_table_handler(norm_name); |
| 16518 | |||
| 16519 |
2/2✓ Branch 0 taken 110974 times.
✓ Branch 1 taken 206797 times.
|
635542 | if (handler != nullptr) { |
| 16520 |
6/10✓ Branch 0 taken 110974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 113086 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 224060 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 113086 times.
✓ Branch 9 taken 110974 times.
|
670068 | for (auto index : handler->indexes) { |
| 16521 |
2/2✓ Branch 0 taken 54161 times.
✓ Branch 1 taken 58925 times.
|
226172 | if (index->last_ins_cur) { |
| 16522 | /* last_ins_cur and last_sel_cur are allocated together, therefore only | ||
| 16523 | checking last_ins_cur before releasing mtr */ | ||
| 16524 |
1/2✓ Branch 0 taken 54161 times.
✗ Branch 1 not taken.
|
108322 | index->last_ins_cur->release(); |
| 16525 |
1/2✓ Branch 0 taken 54161 times.
✗ Branch 1 not taken.
|
108322 | index->last_sel_cur->release(); |
| 16526 | } | ||
| 16527 | } | ||
| 16528 |
2/2✓ Branch 0 taken 206791 times.
✓ Branch 1 taken 6 times.
|
413594 | } else if (srv_read_only_mode || |
| 16529 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 206791 times.
|
413582 | srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) { |
| 16530 | 12 | return (HA_ERR_TABLE_READONLY); | |
| 16531 | } | ||
| 16532 | |||
| 16533 |
1/2✓ Branch 0 taken 317764 times.
✗ Branch 1 not taken.
|
635530 | trx_t *trx = check_trx_exists(thd); |
| 16534 | |||
| 16535 |
1/2✓ Branch 0 taken 317765 times.
✗ Branch 1 not taken.
|
635528 | TrxInInnoDB trx_in_innodb(trx); |
| 16536 | |||
| 16537 | 635530 | ulint name_len = strlen(name); | |
| 16538 | |||
| 16539 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 317765 times.
|
635530 | ut_a(name_len < 1000); |
| 16540 | |||
| 16541 | /* Either the transaction is already flagged as a locking transaction | ||
| 16542 | or it hasn't been started yet. */ | ||
| 16543 | |||
| 16544 |
5/8✓ Branch 0 taken 317764 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 138096 times.
✓ Branch 3 taken 179668 times.
✓ Branch 4 taken 138096 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 317766 times.
|
635530 | ut_a(!trx_is_started(trx) || trx->will_lock > 0); |
| 16545 | |||
| 16546 | /* We are doing a DDL operation. */ | ||
| 16547 | 635532 | ++trx->will_lock; | |
| 16548 | |||
| 16549 | 635532 | bool file_per_table = false; | |
| 16550 |
7/8✓ Branch 0 taken 206791 times.
✓ Branch 1 taken 110975 times.
✓ Branch 2 taken 206790 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 164264 times.
✓ Branch 5 taken 42526 times.
✓ Branch 6 taken 164264 times.
✓ Branch 7 taken 153501 times.
|
635532 | if (dd_tab != nullptr && dd_tab->is_persistent()) { |
| 16551 | dict_table_t *tab; | ||
| 16552 | |||
| 16553 |
1/2✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
|
328528 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 16554 |
1/2✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
|
328528 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 16555 | |||
| 16556 |
2/3✓ Branch 0 taken 34678 times.
✓ Branch 1 taken 129586 times.
✗ Branch 2 not taken.
|
397884 | int err = dd_table_open_on_dd_obj( |
| 16557 |
1/2✓ Branch 0 taken 34678 times.
✗ Branch 1 not taken.
|
69356 | thd, client, dd_tab->table(), |
| 16558 |
5/7✓ Branch 0 taken 34678 times.
✓ Branch 1 taken 129586 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34678 times.
✓ Branch 4 taken 129586 times.
✓ Branch 5 taken 34678 times.
✗ Branch 6 not taken.
|
328528 | (!dd_table_is_partitioned(dd_tab->table()) |
| 16559 | ? nullptr | ||
| 16560 | : reinterpret_cast<const dd::Partition *>(dd_tab)), | ||
| 16561 | norm_name, tab, td); | ||
| 16562 | |||
| 16563 |
2/4✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 164264 times.
✗ Branch 3 not taken.
|
328528 | if (err == 0 && tab != nullptr) { |
| 16564 |
10/11✓ Branch 0 taken 130034 times.
✓ Branch 1 taken 34230 times.
✓ Branch 2 taken 16867 times.
✓ Branch 3 taken 113167 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 16867 times.
✓ Branch 6 taken 113167 times.
✓ Branch 7 taken 16867 times.
✓ Branch 8 taken 129586 times.
✓ Branch 9 taken 16867 times.
✓ Branch 10 taken 17811 times.
|
328528 | if (tab->can_be_evicted && dd_table_is_partitioned(dd_tab->table())) { |
| 16565 |
1/2✓ Branch 0 taken 16867 times.
✗ Branch 1 not taken.
|
33734 | dict_sys_mutex_enter(); |
| 16566 |
1/2✓ Branch 0 taken 16867 times.
✗ Branch 1 not taken.
|
33734 | dict_table_ddl_acquire(tab); |
| 16567 |
1/2✓ Branch 0 taken 16867 times.
✗ Branch 1 not taken.
|
33734 | dict_sys_mutex_exit(); |
| 16568 | } | ||
| 16569 | |||
| 16570 |
1/2✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
|
328528 | file_per_table = dict_table_is_file_per_table(tab); |
| 16571 |
1/2✓ Branch 0 taken 164264 times.
✗ Branch 1 not taken.
|
328528 | dd_table_close(tab, thd, nullptr, false); |
| 16572 | } | ||
| 16573 | 328528 | } | |
| 16574 | |||
| 16575 |
1/2✓ Branch 0 taken 317733 times.
✗ Branch 1 not taken.
|
635530 | error = row_drop_table_for_mysql(norm_name, trx, true, handler); |
| 16576 | |||
| 16577 |
3/4✓ Branch 0 taken 110974 times.
✓ Branch 1 taken 206759 times.
✓ Branch 2 taken 110974 times.
✗ Branch 3 not taken.
|
635466 | if (handler != nullptr && error == DB_SUCCESS) { |
| 16578 |
1/2✓ Branch 0 taken 110974 times.
✗ Branch 1 not taken.
|
221948 | priv->unregister_table_handler(norm_name); |
| 16579 | } | ||
| 16580 | |||
| 16581 |
4/4✓ Branch 0 taken 317731 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 152951 times.
✓ Branch 3 taken 164780 times.
|
635466 | if (error == DB_SUCCESS && file_per_table) { |
| 16582 |
2/4✓ Branch 0 taken 152951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 152951 times.
✗ Branch 3 not taken.
|
305902 | dd::Object_id dd_space_id = dd_first_index(dd_tab)->tablespace_id(); |
| 16583 |
1/2✓ Branch 0 taken 152951 times.
✗ Branch 1 not taken.
|
305902 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 16584 |
1/2✓ Branch 0 taken 152951 times.
✗ Branch 1 not taken.
|
305902 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 16585 | |||
| 16586 |
3/4✓ Branch 0 taken 152951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 152949 times.
|
305902 | if (dd_drop_tablespace(client, dd_space_id)) { |
| 16587 | 4 | error = DB_ERROR; | |
| 16588 | } | ||
| 16589 | 305902 | } | |
| 16590 | |||
| 16591 |
1/2✓ Branch 0 taken 317733 times.
✗ Branch 1 not taken.
|
635466 | return (convert_error_code_to_mysql(error, 0, nullptr)); |
| 16592 | 635466 | } | |
| 16593 | |||
| 16594 | template int innobase_basic_ddl::delete_impl<dd::Table>(THD *, const char *, | ||
| 16595 | const dd::Table *, | ||
| 16596 | const TABLE *); | ||
| 16597 | |||
| 16598 | template int innobase_basic_ddl::delete_impl<dd::Partition>( | ||
| 16599 | THD *, const char *, const dd::Partition *, const TABLE *); | ||
| 16600 | |||
| 16601 | template <typename Table> | ||
| 16602 | 56852 | int innobase_basic_ddl::rename_impl(THD *thd, const char *from, const char *to, | |
| 16603 | const Table *from_table, | ||
| 16604 | const Table *to_table, const TABLE *td) { | ||
| 16605 | dberr_t error; | ||
| 16606 | char norm_to[FN_REFLEN]; | ||
| 16607 | char norm_from[FN_REFLEN]; | ||
| 16608 | 56852 | bool rename_file = false; | |
| 16609 | 56852 | space_id_t space = SPACE_UNKNOWN; | |
| 16610 | 56852 | dict_table_t *table = nullptr; | |
| 16611 | |||
| 16612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28426 times.
|
56852 | ut_ad(!srv_read_only_mode); |
| 16613 | |||
| 16614 |
3/6✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28426 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 28426 times.
|
113704 | if (!normalize_table_name(norm_to, to) || |
| 16615 |
2/4✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28426 times.
|
56852 | !normalize_table_name(norm_from, from)) { |
| 16616 | /* purecov: begin inspected */ | ||
| 16617 | ✗ | ut_d(ut_error); | |
| 16618 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 16619 | /* purecov: end */ | ||
| 16620 | } | ||
| 16621 | |||
| 16622 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28426 times.
|
56852 | ut_ad(strcmp(norm_from, norm_to) != 0); |
| 16623 | |||
| 16624 |
3/4✓ Branch 0 taken 28168 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 28168 times.
✗ Branch 3 not taken.
|
56852 | DEBUG_SYNC_C("innodb_rename_table_ready"); |
| 16625 | |||
| 16626 |
1/2✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
|
56852 | trx_t *trx = check_trx_exists(thd); |
| 16627 | |||
| 16628 |
1/2✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
|
56852 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 16629 | |||
| 16630 |
1/2✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
|
56852 | TrxInInnoDB trx_in_innodb(trx); |
| 16631 | |||
| 16632 | 56852 | ++trx->will_lock; | |
| 16633 | |||
| 16634 |
1/2✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
|
56852 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 16635 |
1/2✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
|
56852 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 16636 | |||
| 16637 |
2/3✓ Branch 0 taken 11317 times.
✓ Branch 1 taken 17109 times.
✗ Branch 2 not taken.
|
79486 | int err = dd_table_open_on_dd_obj( |
| 16638 |
1/2✓ Branch 0 taken 11317 times.
✗ Branch 1 not taken.
|
22634 | thd, client, from_table->table(), |
| 16639 |
5/7✓ Branch 0 taken 11317 times.
✓ Branch 1 taken 17109 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11317 times.
✓ Branch 4 taken 17109 times.
✓ Branch 5 taken 11317 times.
✗ Branch 6 not taken.
|
56852 | (!dd_table_is_partitioned(from_table->table()) |
| 16640 | ? nullptr | ||
| 16641 | : reinterpret_cast<const dd::Partition *>(from_table)), | ||
| 16642 | norm_from, table, td); | ||
| 16643 |
2/4✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28426 times.
|
56852 | if (err != 0 || table == nullptr) { |
| 16644 | ✗ | error = DB_TABLE_NOT_FOUND; | |
| 16645 | ✗ | return (convert_error_code_to_mysql(error, 0, nullptr)); | |
| 16646 | } | ||
| 16647 | |||
| 16648 |
1/2✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
|
56852 | rename_file = dict_table_is_file_per_table(table); |
| 16649 | 56852 | space = table->space; | |
| 16650 | |||
| 16651 |
1/2✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
|
56852 | if (row_is_mysql_tmp_table_name(norm_from) && |
| 16652 |
6/8✓ Branch 0 taken 10916 times.
✓ Branch 1 taken 17510 times.
✓ Branch 2 taken 10916 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10916 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7139 times.
✓ Branch 7 taken 21287 times.
|
78684 | !row_is_mysql_tmp_table_name(norm_to) && |
| 16653 |
4/7✓ Branch 0 taken 3777 times.
✓ Branch 1 taken 7139 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10916 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 3777 times.
|
21832 | !dd_table_is_partitioned(from_table->table())) { |
| 16654 | 14278 | table->refresh_fk = true; | |
| 16655 | } | ||
| 16656 | |||
| 16657 |
5/7✓ Branch 0 taken 11317 times.
✓ Branch 1 taken 17109 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11317 times.
✓ Branch 4 taken 17109 times.
✓ Branch 5 taken 11317 times.
✗ Branch 6 not taken.
|
56852 | if (dd_table_is_partitioned(from_table->table())) { |
| 16658 |
1/2✓ Branch 0 taken 11317 times.
✗ Branch 1 not taken.
|
22634 | dict_sys_mutex_enter(); |
| 16659 |
1/2✓ Branch 0 taken 11317 times.
✗ Branch 1 not taken.
|
22634 | dict_table_ddl_acquire(table); |
| 16660 |
1/2✓ Branch 0 taken 11317 times.
✗ Branch 1 not taken.
|
22634 | dict_sys_mutex_exit(); |
| 16661 | } | ||
| 16662 | |||
| 16663 |
1/2✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
|
56852 | dd_table_close(table, thd, nullptr, false); |
| 16664 | |||
| 16665 | /* Serialize data dictionary operations with dictionary mutex: | ||
| 16666 | no deadlocks can occur then in these operations. */ | ||
| 16667 | |||
| 16668 |
1/2✓ Branch 0 taken 28426 times.
✗ Branch 1 not taken.
|
56852 | row_mysql_lock_data_dictionary(trx, UT_LOCATION_HERE); |
| 16669 | |||
| 16670 |
3/5✓ Branch 0 taken 11317 times.
✓ Branch 1 taken 17058 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11266 times.
✗ Branch 4 not taken.
|
56852 | error = row_rename_table_for_mysql(norm_from, norm_to, &to_table->table(), |
| 16671 | trx, false); | ||
| 16672 | |||
| 16673 |
1/2✓ Branch 0 taken 28324 times.
✗ Branch 1 not taken.
|
56648 | row_mysql_unlock_data_dictionary(trx); |
| 16674 | |||
| 16675 |
4/4✓ Branch 0 taken 28306 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 21566 times.
✓ Branch 3 taken 6740 times.
|
56648 | if (error == DB_SUCCESS && rename_file) { |
| 16676 |
1/2✓ Branch 0 taken 21566 times.
✗ Branch 1 not taken.
|
43132 | char *new_path = fil_space_get_first_path(space); |
| 16677 | |||
| 16678 |
2/4✓ Branch 0 taken 21566 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21566 times.
✗ Branch 3 not taken.
|
43132 | auto dd_space_id = dd_first_index(to_table)->tablespace_id(); |
| 16679 | |||
| 16680 |
1/2✓ Branch 0 taken 21566 times.
✗ Branch 1 not taken.
|
43132 | error = dd_tablespace_rename(dd_space_id, false, norm_to, new_path); |
| 16681 | |||
| 16682 |
2/2✓ Branch 0 taken 21550 times.
✓ Branch 1 taken 16 times.
|
43132 | if (new_path != nullptr) { |
| 16683 | 43100 | ut::free(new_path); | |
| 16684 | } | ||
| 16685 | } | ||
| 16686 | |||
| 16687 |
3/4✓ Branch 0 taken 28066 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 28066 times.
✗ Branch 3 not taken.
|
56648 | DEBUG_SYNC(thd, "after_innobase_rename_table"); |
| 16688 | |||
| 16689 |
2/2✓ Branch 0 taken 28306 times.
✓ Branch 1 taken 18 times.
|
56648 | if (error == DB_SUCCESS) { |
| 16690 | char errstr[512]; | ||
| 16691 | dberr_t ret; | ||
| 16692 | |||
| 16693 |
1/2✓ Branch 0 taken 28306 times.
✗ Branch 1 not taken.
|
56612 | ret = dict_stats_rename_table(norm_from, norm_to, errstr, sizeof(errstr)); |
| 16694 | |||
| 16695 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28306 times.
|
56612 | if (ret != DB_SUCCESS) { |
| 16696 | ✗ | ib::error(ER_IB_MSG_566) << errstr; | |
| 16697 | |||
| 16698 | ✗ | push_warning(thd, Sql_condition::SL_WARNING, ER_LOCK_WAIT_TIMEOUT, | |
| 16699 | errstr); | ||
| 16700 | } | ||
| 16701 | } | ||
| 16702 | |||
| 16703 | /* The duplicate key scenario was possible only for old DD since InnoDB | ||
| 16704 | would update it internally. With new DD, the rename conflict should be | ||
| 16705 | checked by server before diving into SE */ | ||
| 16706 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28324 times.
|
56648 | ut_ad(error != DB_DUPLICATE_KEY); |
| 16707 | |||
| 16708 |
1/2✓ Branch 0 taken 28324 times.
✗ Branch 1 not taken.
|
56648 | return (convert_error_code_to_mysql(error, 0, nullptr)); |
| 16709 | 56648 | } | |
| 16710 | |||
| 16711 | template int innobase_basic_ddl::rename_impl<dd::Table>(THD *, const char *, | ||
| 16712 | const char *, | ||
| 16713 | const dd::Table *, | ||
| 16714 | const dd::Table *, | ||
| 16715 | const TABLE *); | ||
| 16716 | |||
| 16717 | template int innobase_basic_ddl::rename_impl<dd::Partition>( | ||
| 16718 | THD *, const char *, const char *, const dd::Partition *, | ||
| 16719 | const dd::Partition *, const TABLE *); | ||
| 16720 | |||
| 16721 | template <typename Table> | ||
| 16722 | 33364 | innobase_truncate<Table>::~innobase_truncate() { | |
| 16723 |
2/2✓ Branch 0 taken 16680 times.
✓ Branch 1 taken 2 times.
|
33364 | if (m_table != nullptr) { |
| 16724 | 33360 | dd_table_close(m_table, m_thd, nullptr, false); | |
| 16725 | 33360 | m_table = nullptr; | |
| 16726 | } | ||
| 16727 | 33364 | } | |
| 16728 | |||
| 16729 | template innobase_truncate<dd::Table>::~innobase_truncate(); | ||
| 16730 | template innobase_truncate<dd::Partition>::~innobase_truncate(); | ||
| 16731 | |||
| 16732 | template <typename Table> | ||
| 16733 | 33396 | int innobase_truncate<Table>::open_table(dict_table_t *&innodb_table) { | |
| 16734 |
2/2✓ Branch 0 taken 16651 times.
✓ Branch 1 taken 47 times.
|
33396 | if (m_dd_table->table().is_persistent()) { |
| 16735 |
1/2✓ Branch 0 taken 16651 times.
✗ Branch 1 not taken.
|
33302 | dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd); |
| 16736 |
1/2✓ Branch 0 taken 16651 times.
✗ Branch 1 not taken.
|
33302 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 16737 | |||
| 16738 |
1/2✓ Branch 0 taken 10784 times.
✗ Branch 1 not taken.
|
54870 | int error = dd_table_open_on_dd_obj( |
| 16739 |
2/4✓ Branch 0 taken 5867 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5867 times.
✗ Branch 3 not taken.
|
33302 | m_thd, client, m_dd_table->table(), |
| 16740 |
3/4✓ Branch 0 taken 16651 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5867 times.
✓ Branch 3 taken 10784 times.
|
33302 | (dd_table_is_partitioned(m_dd_table->table()) |
| 16741 | ? reinterpret_cast<const dd::Partition *>(m_dd_table) | ||
| 16742 | : nullptr), | ||
| 16743 |
1/2✓ Branch 0 taken 5867 times.
✗ Branch 1 not taken.
|
33302 | m_name, innodb_table, m_form); |
| 16744 | |||
| 16745 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16651 times.
|
33302 | if (error != 0) { |
| 16746 | ✗ | return (error); | |
| 16747 | } | ||
| 16748 |
1/2✓ Branch 0 taken 16651 times.
✗ Branch 1 not taken.
|
33302 | } else { |
| 16749 | 94 | innodb_table = dd_table_open_on_name_in_mem(m_name, false); | |
| 16750 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
|
94 | ut_ad(innodb_table->is_temporary()); |
| 16751 | } | ||
| 16752 | |||
| 16753 | 33396 | m_table = innodb_table; | |
| 16754 | |||
| 16755 | 33396 | return (0); | |
| 16756 | } | ||
| 16757 | |||
| 16758 | template int innobase_truncate<dd::Table>::open_table( | ||
| 16759 | dict_table_t *&innodb_table); | ||
| 16760 | template int innobase_truncate<dd::Partition>::open_table( | ||
| 16761 | dict_table_t *&innodb_table); | ||
| 16762 | |||
| 16763 | template <typename Table> | ||
| 16764 | 32530 | int innobase_truncate<Table>::prepare() { | |
| 16765 | 32530 | int error = 0; | |
| 16766 | |||
| 16767 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16265 times.
|
32530 | if (m_table == nullptr) { |
| 16768 | ✗ | error = open_table(m_table); | |
| 16769 | |||
| 16770 | ✗ | if (error != 0) { | |
| 16771 | ✗ | return (error); | |
| 16772 | } | ||
| 16773 | } | ||
| 16774 | |||
| 16775 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16265 times.
|
32530 | ut_ad(m_table != nullptr); |
| 16776 | |||
| 16777 |
1/2✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
|
32530 | m_trx = check_trx_exists(m_thd); |
| 16778 |
1/2✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
|
32530 | m_file_per_table = dict_table_is_file_per_table(m_table); |
| 16779 | 32530 | m_flags = m_table->flags; | |
| 16780 | 32530 | m_flags2 = m_table->flags2; | |
| 16781 | |||
| 16782 |
1/2✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
|
32530 | update_create_info_from_table(&m_create_info, m_form); |
| 16783 | |||
| 16784 |
1/2✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
|
32530 | dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd); |
| 16785 |
1/2✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
|
32530 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 16786 | |||
| 16787 | /* Get the autoextend_size attribute value for the table being | ||
| 16788 | truncated. This values will be used to create the new table as | ||
| 16789 | part of truncate. */ | ||
| 16790 | 32530 | uint64_t autoextend_size{}; | |
| 16791 | |||
| 16792 |
2/4✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16265 times.
✗ Branch 3 not taken.
|
32530 | dd::Object_id space_id = dd_first_index(m_dd_table)->tablespace_id(); |
| 16793 | |||
| 16794 |
2/2✓ Branch 0 taken 13621 times.
✓ Branch 1 taken 2644 times.
|
32530 | if (m_file_per_table) { |
| 16795 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | dd_get_tablespace_size_option(client, space_id, &autoextend_size); |
| 16796 | } | ||
| 16797 | |||
| 16798 | 32530 | m_create_info.m_implicit_tablespace_autoextend_size = autoextend_size; | |
| 16799 | |||
| 16800 | 32530 | m_create_info.tablespace = nullptr; | |
| 16801 |
3/4✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 16218 times.
|
32530 | if (m_table->is_temporary()) { |
| 16802 | 94 | m_create_info.options |= HA_LEX_CREATE_TMP_TABLE; | |
| 16803 | } else { | ||
| 16804 |
2/2✓ Branch 0 taken 1555 times.
✓ Branch 1 taken 14663 times.
|
32436 | if (m_table->tablespace != nullptr) { |
| 16805 |
1/2✓ Branch 0 taken 1555 times.
✗ Branch 1 not taken.
|
3110 | m_create_info.tablespace = mem_strdup(m_table->tablespace); |
| 16806 | } | ||
| 16807 | } | ||
| 16808 | |||
| 16809 | 32530 | m_create_info.key_block_size = m_form->s->key_block_size; | |
| 16810 | |||
| 16811 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 16245 times.
|
32530 | if (m_table->data_dir_path != nullptr) { |
| 16812 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
40 | m_create_info.data_file_name = mem_strdup(m_table->data_dir_path); |
| 16813 | } else { | ||
| 16814 | 32490 | m_create_info.data_file_name = nullptr; | |
| 16815 | } | ||
| 16816 | |||
| 16817 |
2/2✓ Branch 0 taken 9653 times.
✓ Branch 1 taken 6612 times.
|
32530 | if (m_table->can_be_evicted) { |
| 16818 |
1/2✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
|
19306 | dict_sys_mutex_enter(); |
| 16819 |
1/2✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
|
19306 | dict_table_ddl_acquire(m_table); |
| 16820 |
1/2✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
|
19306 | dict_sys_mutex_exit(); |
| 16821 | } | ||
| 16822 | |||
| 16823 |
2/2✓ Branch 0 taken 15795 times.
✓ Branch 1 taken 470 times.
|
32530 | if (!dict_table_has_autoinc_col(m_table)) { |
| 16824 | 31590 | m_keep_autoinc = false; | |
| 16825 | } | ||
| 16826 | |||
| 16827 | 32530 | return (error); | |
| 16828 | 32530 | } | |
| 16829 | |||
| 16830 | template <typename Table> | ||
| 16831 | 32530 | int innobase_truncate<Table>::truncate() { | |
| 16832 | 32530 | int error = 0; | |
| 16833 | 32530 | bool reset = false; | |
| 16834 | 32530 | uint64_t autoinc = 0; | |
| 16835 | 32530 | uint64_t autoinc_persisted = 0; | |
| 16836 | |||
| 16837 | /* Rename tablespace file to avoid existing file in create. */ | ||
| 16838 |
2/2✓ Branch 0 taken 13621 times.
✓ Branch 1 taken 2644 times.
|
32530 | if (m_file_per_table) { |
| 16839 | 27242 | error = rename_tablespace(); | |
| 16840 | } | ||
| 16841 | |||
| 16842 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16260 times.
|
32524 | DBUG_EXECUTE_IF("ib_truncate_fail_after_rename", error = HA_ERR_GENERIC;); |
| 16843 | |||
| 16844 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16259 times.
|
32524 | if (error != 0) { |
| 16845 | 6 | return (error); | |
| 16846 | } | ||
| 16847 | |||
| 16848 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 16224 times.
|
32518 | if (m_keep_autoinc) { |
| 16849 | 70 | autoinc_persisted = m_table->autoinc_persisted; | |
| 16850 | 70 | autoinc = m_table->autoinc; | |
| 16851 | } | ||
| 16852 | |||
| 16853 | 32518 | dd_table_close(m_table, m_thd, nullptr, false); | |
| 16854 | 32518 | m_table = nullptr; | |
| 16855 | |||
| 16856 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16258 times.
|
32518 | DBUG_EXECUTE_IF("ib_truncate_crash_after_rename", DBUG_SUICIDE();); |
| 16857 | |||
| 16858 | 32516 | error = innobase_basic_ddl::delete_impl(m_thd, m_name, m_dd_table, nullptr); | |
| 16859 | |||
| 16860 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16253 times.
|
32510 | DBUG_EXECUTE_IF("ib_truncate_fail_after_delete", error = HA_ERR_GENERIC;); |
| 16861 | |||
| 16862 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16253 times.
|
32510 | if (error != 0) { |
| 16863 | 4 | return (error); | |
| 16864 | } | ||
| 16865 | |||
| 16866 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16252 times.
|
32506 | DBUG_EXECUTE_IF("ib_truncate_crash_after_drop_old_table", DBUG_SUICIDE();); |
| 16867 | |||
| 16868 |
2/2✓ Branch 0 taken 16205 times.
✓ Branch 1 taken 47 times.
|
32504 | if (m_dd_table->is_persistent()) { |
| 16869 | 32410 | m_dd_table->set_se_private_id(dd::INVALID_OBJECT_ID); | |
| 16870 |
6/10✓ Branch 0 taken 16205 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16205 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16205 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 31520 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 31520 times.
✓ Branch 9 taken 16205 times.
|
127860 | for (auto dd_index : *m_dd_table->indexes()) { |
| 16871 |
2/4✓ Branch 0 taken 31520 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31520 times.
✗ Branch 3 not taken.
|
63040 | dd_index->se_private_data().clear(); |
| 16872 | } | ||
| 16873 | } | ||
| 16874 | |||
| 16875 | 32504 | if (dd_table_is_partitioned(m_dd_table->table()) && | |
| 16876 |
4/6✓ Branch 0 taken 5436 times.
✓ Branch 1 taken 10816 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5436 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 16252 times.
|
32504 | m_create_info.tablespace != nullptr && |
| 16877 | ✗ | m_dd_table->tablespace_id() == dd::INVALID_OBJECT_ID) { | |
| 16878 | /* Don't change the tablespace if it's a partitioned table, | ||
| 16879 | so temporarily set the tablespace_id as an explicit one | ||
| 16880 | to make it consistent with info->tablespace */ | ||
| 16881 | ✗ | m_dd_table->set_tablespace_id(dd_first_index(m_dd_table)->tablespace_id()); | |
| 16882 | ✗ | reset = true; | |
| 16883 | } | ||
| 16884 | |||
| 16885 | 32504 | m_trx->in_truncate = true; | |
| 16886 | 32504 | bool inherit_metadata = false; | |
| 16887 | 32504 | if (dd_table_has_instant_cols(m_dd_table->table()) && | |
| 16888 |
8/8✓ Branch 0 taken 55 times.
✓ Branch 1 taken 16197 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 15 times.
✓ Branch 7 taken 16237 times.
|
32504 | dd_table_is_partitioned(m_dd_table->table()) && !m_table_truncate) { |
| 16889 | /* For a partition table, if this is not a full table truncate, and first | ||
| 16890 | partition is getting truncated, make sure INSTANT metadata is inherited. */ | ||
| 16891 | 30 | inherit_metadata = true; | |
| 16892 | } | ||
| 16893 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 16237 times.
|
32504 | error = innobase_basic_ddl::create_impl( |
| 16894 | 32504 | m_thd, m_name, m_form, &m_create_info, m_dd_table, m_file_per_table, | |
| 16895 | false, true, m_flags, m_flags2, | ||
| 16896 | 30 | inherit_metadata ? &m_dd_table->table() : nullptr); | |
| 16897 | 32492 | m_trx->in_truncate = false; | |
| 16898 | |||
| 16899 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16246 times.
|
32492 | if (reset) { |
| 16900 | ✗ | m_dd_table->set_tablespace_id(dd::INVALID_OBJECT_ID); | |
| 16901 | } | ||
| 16902 | |||
| 16903 |
1/2✓ Branch 0 taken 16246 times.
✗ Branch 1 not taken.
|
32492 | if (error == 0) { |
| 16904 | 32492 | dict_sys_mutex_enter(); | |
| 16905 | 32492 | m_table = dict_table_check_if_in_cache_low(m_name); | |
| 16906 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16246 times.
|
32492 | ut_ad(m_table != nullptr); |
| 16907 | 32492 | m_table->acquire(); | |
| 16908 | |||
| 16909 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 16212 times.
|
32492 | if (m_keep_autoinc) { |
| 16910 | 68 | m_table->autoinc_persisted = autoinc_persisted; | |
| 16911 | 68 | m_table->autoinc = autoinc; | |
| 16912 | } | ||
| 16913 | |||
| 16914 | 32492 | dict_sys_mutex_exit(); | |
| 16915 | } | ||
| 16916 | |||
| 16917 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16244 times.
|
32492 | DBUG_EXECUTE_IF("ib_truncate_fail_after_create_new_table", |
| 16918 | error = HA_ERR_GENERIC;); | ||
| 16919 | |||
| 16920 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16245 times.
|
32492 | DBUG_EXECUTE_IF("ib_truncate_crash_after_create_new_table", DBUG_SUICIDE();); |
| 16921 | |||
| 16922 | 32490 | return (error); | |
| 16923 | } | ||
| 16924 | |||
| 16925 | template <typename Table> | ||
| 16926 | 27242 | int innobase_truncate<Table>::rename_tablespace() { | |
| 16927 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13621 times.
|
27242 | ut_ad(m_table != nullptr); |
| 16928 |
2/4✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13621 times.
|
27242 | ut_ad(dict_table_is_file_per_table(m_table)); |
| 16929 |
2/4✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13621 times.
|
27242 | ut_ad(!m_table->is_temporary()); |
| 16930 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13621 times.
|
27242 | ut_ad(m_table->trunc_name.m_name == nullptr); |
| 16931 | |||
| 16932 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | uint64_t old_size = mem_heap_get_size(m_table->heap); |
| 16933 | 54484 | char *temp_name = dict_mem_create_temporary_tablename( | |
| 16934 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | m_table->heap, m_table->name.m_name, m_table->id); |
| 16935 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | uint64_t new_size = mem_heap_get_size(m_table->heap); |
| 16936 | |||
| 16937 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | dict_sys_mutex_enter(); |
| 16938 | 27242 | dict_sys->size += new_size - old_size; | |
| 16939 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | dict_sys_mutex_exit(); |
| 16940 | |||
| 16941 | 27242 | std::string new_path; | |
| 16942 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | char *old_path = fil_space_get_first_path(m_table->space); |
| 16943 | |||
| 16944 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 13601 times.
|
27242 | if (DICT_TF_HAS_DATA_DIR(m_table->flags)) { |
| 16945 |
3/6✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | new_path = Fil_path::make_new_path(old_path, temp_name, IBD); |
| 16946 | } else { | ||
| 16947 |
2/4✓ Branch 0 taken 13601 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13601 times.
✗ Branch 3 not taken.
|
27202 | char *ptr = Fil_path::make_ibd_from_table_name(temp_name); |
| 16948 |
1/2✓ Branch 0 taken 13601 times.
✗ Branch 1 not taken.
|
27202 | new_path.assign(ptr); |
| 16949 | 27202 | ut::free(ptr); | |
| 16950 | } | ||
| 16951 | |||
| 16952 | /* New filepath must not exist. */ | ||
| 16953 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | dberr_t err = fil_rename_tablespace_check(m_table->space, old_path, |
| 16954 | new_path.c_str(), false); | ||
| 16955 | |||
| 16956 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | if (err == DB_SUCCESS) { |
| 16957 |
1/2✓ Branch 0 taken 13621 times.
✗ Branch 1 not taken.
|
27242 | dict_sys_mutex_enter(); |
| 16958 |
1/2✓ Branch 0 taken 13618 times.
✗ Branch 1 not taken.
|
27242 | err = fil_rename_tablespace(m_table->space, old_path, temp_name, |
| 16959 | new_path.c_str()); | ||
| 16960 |
1/2✓ Branch 0 taken 13618 times.
✗ Branch 1 not taken.
|
27236 | dict_sys_mutex_exit(); |
| 16961 | |||
| 16962 |
2/2✓ Branch 0 taken 13617 times.
✓ Branch 1 taken 1 times.
|
27236 | if (err == DB_SUCCESS) { |
| 16963 | 27234 | m_table->trunc_name.m_name = temp_name; | |
| 16964 | } | ||
| 16965 | } | ||
| 16966 | |||
| 16967 | 27236 | ut::free(old_path); | |
| 16968 | |||
| 16969 |
1/2✓ Branch 0 taken 13618 times.
✗ Branch 1 not taken.
|
54472 | return (convert_error_code_to_mysql(err, m_table->flags, nullptr)); |
| 16970 | 27236 | } | |
| 16971 | |||
| 16972 | template <typename Table> | ||
| 16973 | 32500 | void innobase_truncate<Table>::cleanup() { | |
| 16974 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16248 times.
|
32500 | if (m_table == nullptr) { |
| 16975 | 4 | m_table = dd_table_open_on_name_in_mem(m_name, false); | |
| 16976 | } | ||
| 16977 | |||
| 16978 |
2/2✓ Branch 0 taken 16248 times.
✓ Branch 1 taken 2 times.
|
32500 | if (m_table != nullptr) { |
| 16979 | 32496 | m_table->trunc_name.m_name = nullptr; | |
| 16980 | } | ||
| 16981 | |||
| 16982 | 32500 | char *tablespace = const_cast<char *>(m_create_info.tablespace); | |
| 16983 | 32500 | char *data_file_name = const_cast<char *>(m_create_info.data_file_name); | |
| 16984 | |||
| 16985 | 32500 | ut::free(tablespace); | |
| 16986 | 32500 | ut::free(data_file_name); | |
| 16987 | 32500 | } | |
| 16988 | |||
| 16989 | template <typename Table> | ||
| 16990 | 32486 | int innobase_truncate<Table>::load_fk() { | |
| 16991 |
5/7✓ Branch 0 taken 5435 times.
✓ Branch 1 taken 10808 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5435 times.
✓ Branch 4 taken 10808 times.
✓ Branch 5 taken 5435 times.
✗ Branch 6 not taken.
|
32486 | if (dd_table_is_partitioned(m_dd_table->table())) { |
| 16992 | 10870 | return (0); | |
| 16993 | } | ||
| 16994 | |||
| 16995 | 21616 | int error = 0; | |
| 16996 |
1/2✓ Branch 0 taken 10808 times.
✗ Branch 1 not taken.
|
21616 | dict_names_t fk_tables; |
| 16997 |
1/2✓ Branch 0 taken 10808 times.
✗ Branch 1 not taken.
|
21616 | dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd); |
| 16998 |
1/2✓ Branch 0 taken 10808 times.
✗ Branch 1 not taken.
|
21616 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 16999 | |||
| 17000 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10808 times.
|
21616 | ut_ad(m_table != nullptr); |
| 17001 | 21616 | error = | |
| 17002 |
1/2✓ Branch 0 taken 10808 times.
✗ Branch 1 not taken.
|
21616 | dd_table_check_for_child(client, m_table->name.m_name, nullptr, m_table, |
| 17003 | true, DICT_ERR_IGNORE_NONE, &fk_tables); | ||
| 17004 | |||
| 17005 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10808 times.
|
21616 | ut_ad(fk_tables.empty()); |
| 17006 | |||
| 17007 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10808 times.
|
21616 | if (error != DB_SUCCESS) { |
| 17008 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 17009 | HA_ERR_CANNOT_ADD_FOREIGN, | ||
| 17010 | "Truncate table '%s' failed to load some" | ||
| 17011 | " foreign key constraints.", | ||
| 17012 | m_name); | ||
| 17013 | } else { | ||
| 17014 | 21616 | error = 0; | |
| 17015 | } | ||
| 17016 | |||
| 17017 | 21616 | return (error); | |
| 17018 | } | ||
| 17019 | |||
| 17020 | template <typename Table> | ||
| 17021 | 32530 | int innobase_truncate<Table>::exec() { | |
| 17022 | 32530 | int error = 0; | |
| 17023 | |||
| 17024 | 32530 | error = prepare(); | |
| 17025 | |||
| 17026 |
1/2✓ Branch 0 taken 16265 times.
✗ Branch 1 not taken.
|
32530 | if (error == 0) { |
| 17027 | 32530 | error = truncate(); | |
| 17028 | } | ||
| 17029 | |||
| 17030 | 32500 | cleanup(); | |
| 17031 | |||
| 17032 |
2/2✓ Branch 0 taken 16243 times.
✓ Branch 1 taken 7 times.
|
32500 | if (error == 0) { |
| 17033 | 32486 | error = load_fk(); | |
| 17034 | } | ||
| 17035 | |||
| 17036 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16249 times.
|
32500 | DBUG_EXECUTE_IF("ib_truncate_crash_after_innodb_complete", DBUG_SUICIDE();); |
| 17037 | |||
| 17038 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16248 times.
|
32498 | DBUG_EXECUTE_IF("ib_truncate_rollback_test", error = HA_ERR_GENERIC;); |
| 17039 | |||
| 17040 | 32498 | return (error); | |
| 17041 | } | ||
| 17042 | |||
| 17043 | template int innobase_truncate<dd::Table>::exec(); | ||
| 17044 | template int innobase_truncate<dd::Partition>::exec(); | ||
| 17045 | |||
| 17046 | /** Check if a column is the only column in an index. | ||
| 17047 | @param[in] index data dictionary index | ||
| 17048 | @param[in] column the column to look for | ||
| 17049 | @return whether the column is the only column in the index */ | ||
| 17050 | 32 | static bool dd_is_only_column(const dd::Index *index, | |
| 17051 | const dd::Column *column) { | ||
| 17052 |
3/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 1 times.
|
63 | return (index->elements().size() == 1 && |
| 17053 |
6/10✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 31 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 29 times.
✓ Branch 9 taken 2 times.
|
63 | &(*index->elements().begin())->column() == column); |
| 17054 | } | ||
| 17055 | |||
| 17056 | /** Add hidden columns and indexes to an InnoDB table definition. | ||
| 17057 | @param[in,out] dd_table data dictionary cache object | ||
| 17058 | @return error number | ||
| 17059 | @retval 0 on success */ | ||
| 17060 | 585282 | int ha_innobase::get_extra_columns_and_keys(const HA_CREATE_INFO *, | |
| 17061 | const List<Create_field> *, | ||
| 17062 | const KEY *, uint, | ||
| 17063 | dd::Table *dd_table) { | ||
| 17064 |
1/2✓ Branch 0 taken 585286 times.
✗ Branch 1 not taken.
|
585282 | DBUG_TRACE; |
| 17065 |
1/2✓ Branch 0 taken 585285 times.
✗ Branch 1 not taken.
|
585286 | THD *thd = ha_thd(); |
| 17066 | 585285 | dd::Index *primary = nullptr; | |
| 17067 | 585285 | bool has_fulltext = false; | |
| 17068 | 585285 | const dd::Index *fts_doc_id_index = nullptr; | |
| 17069 | |||
| 17070 |
6/10✓ Branch 0 taken 585284 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 585284 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585287 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1163991 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1163988 times.
✓ Branch 9 taken 585284 times.
|
1749276 | for (dd::Index *i : *dd_table->indexes()) { |
| 17071 | /* The name "PRIMARY" is reserved for the PRIMARY KEY */ | ||
| 17072 |
4/8✓ Branch 0 taken 1163991 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1163990 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1163991 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1163991 times.
|
1163991 | ut_ad((i->type() == dd::Index::IT_PRIMARY) == |
| 17073 | !my_strcasecmp(system_charset_info, i->name().c_str(), | ||
| 17074 | primary_key_name)); | ||
| 17075 | |||
| 17076 |
4/6✓ Branch 0 taken 1163991 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1163991 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 59 times.
✓ Branch 5 taken 1163932 times.
|
1163991 | if (!my_strcasecmp(system_charset_info, i->name().c_str(), |
| 17077 | FTS_DOC_ID_INDEX_NAME)) { | ||
| 17078 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | ut_ad(!fts_doc_id_index); |
| 17079 |
2/4✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 59 times.
|
59 | ut_ad(i->type() != dd::Index::IT_PRIMARY); |
| 17080 | 59 | fts_doc_id_index = i; | |
| 17081 | } | ||
| 17082 | |||
| 17083 |
5/8✓ Branch 0 taken 1163990 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 605 times.
✓ Branch 5 taken 1161251 times.
✓ Branch 6 taken 2132 times.
✓ Branch 7 taken 2 times.
|
1163991 | switch (i->algorithm()) { |
| 17084 | ✗ | case dd::Index::IA_SE_SPECIFIC: | |
| 17085 | ✗ | ut_d(ut_error); | |
| 17086 | ut_o(break); | ||
| 17087 | ✗ | case dd::Index::IA_HASH: | |
| 17088 | /* This is currently blocked | ||
| 17089 | by ha_innobase::is_index_algorithm_supported(). */ | ||
| 17090 | ✗ | ut_d(ut_error); | |
| 17091 | ut_o(break); | ||
| 17092 | 605 | case dd::Index::IA_RTREE: | |
| 17093 |
2/4✓ Branch 0 taken 605 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 605 times.
✗ Branch 3 not taken.
|
605 | if (i->type() == dd::Index::IT_SPATIAL) { |
| 17094 | 605 | continue; | |
| 17095 | } | ||
| 17096 | ✗ | ut_d(ut_error); | |
| 17097 | ut_o(break); | ||
| 17098 | 1161251 | case dd::Index::IA_BTREE: | |
| 17099 |
5/7✓ Branch 0 taken 1161254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 409088 times.
✓ Branch 3 taken 352527 times.
✓ Branch 4 taken 399638 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
|
1161251 | switch (i->type()) { |
| 17100 | 409088 | case dd::Index::IT_PRIMARY: | |
| 17101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 409089 times.
|
409088 | ut_ad(!primary); |
| 17102 |
4/8✓ Branch 0 taken 409089 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 409087 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 409089 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 409089 times.
|
409089 | ut_ad(i == *dd_table->indexes()->begin()); |
| 17103 | 409089 | primary = i; | |
| 17104 | 409089 | continue; | |
| 17105 | 352527 | case dd::Index::IT_UNIQUE: | |
| 17106 |
7/8✓ Branch 0 taken 37688 times.
✓ Branch 1 taken 314839 times.
✓ Branch 2 taken 37688 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 30748 times.
✓ Branch 5 taken 6940 times.
✓ Branch 6 taken 30748 times.
✓ Branch 7 taken 321779 times.
|
352527 | if (primary == nullptr && i->is_candidate_key()) { |
| 17107 | 30748 | primary = i; | |
| 17108 |
4/8✓ Branch 0 taken 30748 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30748 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 30748 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 30748 times.
|
30748 | ut_ad(*dd_table->indexes()->begin() == i); |
| 17109 | } | ||
| 17110 | 352527 | continue; | |
| 17111 | 399638 | case dd::Index::IT_MULTIPLE: | |
| 17112 | 399638 | continue; | |
| 17113 | ✗ | case dd::Index::IT_FULLTEXT: | |
| 17114 | case dd::Index::IT_SPATIAL: | ||
| 17115 | ✗ | ut_d(ut_error); | |
| 17116 | } | ||
| 17117 | 1 | break; | |
| 17118 | 2132 | case dd::Index::IA_FULLTEXT: | |
| 17119 |
2/4✓ Branch 0 taken 2132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2132 times.
✗ Branch 3 not taken.
|
2132 | if (i->type() == dd::Index::IT_FULLTEXT) { |
| 17120 | 2132 | has_fulltext = true; | |
| 17121 | 2132 | continue; | |
| 17122 | } | ||
| 17123 | ✗ | ut_d(ut_error); | |
| 17124 | ut_o(break); | ||
| 17125 | } | ||
| 17126 | |||
| 17127 |
0/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3 | my_error(ER_UNSUPPORTED_INDEX_ALGORITHM, MYF(0), i->name().c_str()); |
| 17128 | ✗ | return ER_UNSUPPORTED_INDEX_ALGORITHM; | |
| 17129 | } | ||
| 17130 | |||
| 17131 |
2/2✓ Branch 0 taken 1012 times.
✓ Branch 1 taken 584272 times.
|
585284 | if (has_fulltext) { |
| 17132 | /* Add FTS_DOC_ID_INDEX(FTS_DOC_ID) if needed */ | ||
| 17133 | const dd::Column *fts_doc_id = | ||
| 17134 |
1/2✓ Branch 0 taken 1012 times.
✗ Branch 1 not taken.
|
1012 | dd_find_column(dd_table, FTS_DOC_ID_COL_NAME); |
| 17135 | |||
| 17136 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 978 times.
|
1012 | if (fts_doc_id_index) { |
| 17137 |
3/6✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
34 | switch (fts_doc_id_index->type()) { |
| 17138 | ✗ | case dd::Index::IT_PRIMARY: | |
| 17139 | /* PRIMARY!=FTS_DOC_ID_INDEX */ | ||
| 17140 | ✗ | ut_ad(!"wrong fts_doc_id_index"); | |
| 17141 | [[fallthrough]]; | ||
| 17142 | case dd::Index::IT_UNIQUE: | ||
| 17143 | /* We already checked for this. */ | ||
| 17144 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
32 | ut_ad(fts_doc_id_index->algorithm() == dd::Index::IA_BTREE); |
| 17145 |
3/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 3 times.
|
32 | if (dd_is_only_column(fts_doc_id_index, fts_doc_id)) { |
| 17146 | 29 | break; | |
| 17147 | } | ||
| 17148 | [[fallthrough]]; | ||
| 17149 | case dd::Index::IT_MULTIPLE: | ||
| 17150 | case dd::Index::IT_FULLTEXT: | ||
| 17151 | case dd::Index::IT_SPATIAL: | ||
| 17152 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0), |
| 17153 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | fts_doc_id_index->name().c_str()); |
| 17154 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_NAME_FOR_INDEX, |
| 17155 | " InnoDB: Index name " FTS_DOC_ID_INDEX_NAME | ||
| 17156 | " is reserved" | ||
| 17157 | " for UNIQUE INDEX(" FTS_DOC_ID_COL_NAME | ||
| 17158 | ") for " | ||
| 17159 | " FULLTEXT Document ID indexing."); | ||
| 17160 | 5 | return ER_INNODB_FT_WRONG_DOCID_INDEX; | |
| 17161 | } | ||
| 17162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
|
29 | ut_ad(fts_doc_id); |
| 17163 | } | ||
| 17164 | |||
| 17165 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 922 times.
|
1007 | if (fts_doc_id) { |
| 17166 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | if (fts_doc_id->type() != dd::enum_column_types::LONGLONG || |
| 17167 |
7/8✓ Branch 0 taken 73 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 67 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 67 times.
|
152 | fts_doc_id->is_nullable() || |
| 17168 |
3/6✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 67 times.
|
67 | fts_doc_id->name() != FTS_DOC_ID_COL_NAME) { |
| 17169 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN, MYF(0), |
| 17170 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | fts_doc_id->name().c_str()); |
| 17171 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_COLUMN_NAME, |
| 17172 | " InnoDB: Column name " FTS_DOC_ID_COL_NAME | ||
| 17173 | " is reserved for" | ||
| 17174 | " FULLTEXT Document ID indexing."); | ||
| 17175 | 18 | return ER_INNODB_FT_WRONG_DOCID_COLUMN; | |
| 17176 | } | ||
| 17177 | } else { | ||
| 17178 | /* Add hidden FTS_DOC_ID column */ | ||
| 17179 |
1/2✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
|
922 | dd::Column *col = dd_table->add_column(); |
| 17180 |
1/2✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
|
922 | col->set_hidden(dd::Column::enum_hidden_type::HT_HIDDEN_SE); |
| 17181 |
2/4✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 922 times.
✗ Branch 3 not taken.
|
922 | col->set_name(FTS_DOC_ID_COL_NAME); |
| 17182 |
1/2✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
|
922 | col->set_type(dd::enum_column_types::LONGLONG); |
| 17183 |
1/2✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
|
922 | col->set_nullable(false); |
| 17184 |
1/2✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
|
922 | col->set_unsigned(true); |
| 17185 |
1/2✓ Branch 0 taken 922 times.
✗ Branch 1 not taken.
|
922 | col->set_collation_id(1); |
| 17186 | 922 | fts_doc_id = col; | |
| 17187 | } | ||
| 17188 | |||
| 17189 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
|
989 | ut_ad(fts_doc_id); |
| 17190 | |||
| 17191 |
2/2✓ Branch 0 taken 961 times.
✓ Branch 1 taken 28 times.
|
989 | if (fts_doc_id_index == nullptr) { |
| 17192 |
2/4✓ Branch 0 taken 961 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 961 times.
✗ Branch 3 not taken.
|
961 | dd_set_hidden_unique_index(dd_table->add_index(), FTS_DOC_ID_INDEX_NAME, |
| 17193 | fts_doc_id); | ||
| 17194 | } | ||
| 17195 | } | ||
| 17196 | |||
| 17197 |
2/2✓ Branch 0 taken 145445 times.
✓ Branch 1 taken 439816 times.
|
585261 | if (primary == nullptr) { |
| 17198 |
1/2✓ Branch 0 taken 145446 times.
✗ Branch 1 not taken.
|
145445 | dd::Column *db_row_id = dd_add_hidden_column( |
| 17199 | dd_table, "DB_ROW_ID", DATA_ROW_ID_LEN, dd::enum_column_types::INT24); | ||
| 17200 | |||
| 17201 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 145442 times.
|
145446 | if (db_row_id == nullptr) { |
| 17202 | 4 | return ER_WRONG_COLUMN_NAME; | |
| 17203 | } | ||
| 17204 | |||
| 17205 |
2/4✓ Branch 0 taken 145443 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 145443 times.
✗ Branch 3 not taken.
|
145442 | primary = dd_set_hidden_unique_index(dd_table->add_first_index(), |
| 17206 | primary_key_name, db_row_id); | ||
| 17207 | } | ||
| 17208 | |||
| 17209 | /* Add PRIMARY KEY columns to each secondary index, including: | ||
| 17210 | 1. all PRIMARY KEY column prefixes | ||
| 17211 | 2. full PRIMARY KEY columns which don't exist in the secondary index */ | ||
| 17212 | |||
| 17213 | std::vector<const dd::Index_element *, | ||
| 17214 | ut::allocator<const dd::Index_element *>> | ||
| 17215 |
1/2✓ Branch 0 taken 585259 times.
✗ Branch 1 not taken.
|
1170519 | pk_elements; |
| 17216 | |||
| 17217 |
6/10✓ Branch 0 taken 585260 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 585259 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585259 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1310338 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1310333 times.
✓ Branch 9 taken 585260 times.
|
1895597 | for (dd::Index *index : *dd_table->indexes()) { |
| 17218 |
2/2✓ Branch 0 taken 585260 times.
✓ Branch 1 taken 725078 times.
|
1310338 | if (index == primary) { |
| 17219 | 585260 | continue; | |
| 17220 | } | ||
| 17221 | |||
| 17222 | 725078 | pk_elements.clear(); | |
| 17223 |
6/10✓ Branch 0 taken 725078 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 725078 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 725078 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 882400 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 882400 times.
✓ Branch 9 taken 725078 times.
|
1607478 | for (const dd::Index_element *e : primary->elements()) { |
| 17224 |
5/6✓ Branch 0 taken 882400 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 855660 times.
✓ Branch 3 taken 26740 times.
✓ Branch 4 taken 756588 times.
✓ Branch 5 taken 99072 times.
|
1738060 | if (e->is_prefix() || |
| 17225 |
1/2✓ Branch 0 taken 855660 times.
✗ Branch 1 not taken.
|
855660 | std::search_n( |
| 17226 |
4/8✓ Branch 0 taken 855660 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 855660 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 855660 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 855660 times.
✗ Branch 7 not taken.
|
855660 | index->elements().begin(), index->elements().end(), 1, e, |
| 17227 | 1312313 | [](const dd::Index_element *ie, const dd::Index_element *e) { | |
| 17228 | 1312313 | return (&ie->column() == &e->column()); | |
| 17229 |
4/6✓ Branch 0 taken 855660 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 855660 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 783328 times.
✓ Branch 5 taken 99072 times.
|
2593720 | }) == index->elements().end()) { |
| 17230 |
1/2✓ Branch 0 taken 783328 times.
✗ Branch 1 not taken.
|
783328 | pk_elements.push_back(e); |
| 17231 | } | ||
| 17232 | } | ||
| 17233 | |||
| 17234 |
2/2✓ Branch 0 taken 783328 times.
✓ Branch 1 taken 725078 times.
|
1508406 | for (const dd::Index_element *e : pk_elements) { |
| 17235 |
2/4✓ Branch 0 taken 783328 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 783328 times.
✗ Branch 3 not taken.
|
783328 | auto ie = index->add_element(const_cast<dd::Column *>(&e->column())); |
| 17236 |
1/2✓ Branch 0 taken 783328 times.
✗ Branch 1 not taken.
|
783328 | ie->set_hidden(true); |
| 17237 |
2/4✓ Branch 0 taken 783328 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 783328 times.
✗ Branch 3 not taken.
|
783328 | ie->set_order(e->order()); |
| 17238 | } | ||
| 17239 | } | ||
| 17240 | |||
| 17241 | /* Add the InnoDB system columns DB_TRX_ID, DB_ROLL_PTR. */ | ||
| 17242 |
1/2✓ Branch 0 taken 585256 times.
✗ Branch 1 not taken.
|
585260 | dd::Column *db_trx_id = dd_add_hidden_column( |
| 17243 | dd_table, "DB_TRX_ID", DATA_TRX_ID_LEN, dd::enum_column_types::INT24); | ||
| 17244 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 585252 times.
|
585256 | if (db_trx_id == nullptr) { |
| 17245 | 4 | return ER_WRONG_COLUMN_NAME; | |
| 17246 | } | ||
| 17247 | |||
| 17248 | dd::Column *db_roll_ptr = | ||
| 17249 |
1/2✓ Branch 0 taken 585256 times.
✗ Branch 1 not taken.
|
585252 | dd_add_hidden_column(dd_table, "DB_ROLL_PTR", DATA_ROLL_PTR_LEN, |
| 17250 | dd::enum_column_types::LONGLONG); | ||
| 17251 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 585253 times.
|
585256 | if (db_roll_ptr == nullptr) { |
| 17252 | 3 | return ER_WRONG_COLUMN_NAME; | |
| 17253 | } | ||
| 17254 | |||
| 17255 |
1/2✓ Branch 0 taken 585253 times.
✗ Branch 1 not taken.
|
585253 | dd_add_hidden_element(primary, db_trx_id); |
| 17256 |
1/2✓ Branch 0 taken 585252 times.
✗ Branch 1 not taken.
|
585253 | dd_add_hidden_element(primary, db_roll_ptr); |
| 17257 | |||
| 17258 | /* Add all non-virtual columns to the clustered index, | ||
| 17259 | unless they already part of the PRIMARY KEY. */ | ||
| 17260 | |||
| 17261 | 585253 | for (const dd::Column *c : | |
| 17262 |
6/10✓ Branch 0 taken 585252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 585253 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 585253 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5800915 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5800914 times.
✓ Branch 9 taken 585253 times.
|
6971420 | const_cast<const dd::Table *>(dd_table)->columns()) { |
| 17263 |
8/10✓ Branch 0 taken 5800913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4484044 times.
✓ Branch 3 taken 1316869 times.
✓ Branch 4 taken 4484044 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8842 times.
✓ Branch 7 taken 4475202 times.
✓ Branch 8 taken 1325713 times.
✓ Branch 9 taken 4475200 times.
|
5800915 | if (c->is_se_hidden() || c->is_virtual()) { |
| 17264 | 1325713 | continue; | |
| 17265 | } | ||
| 17266 | |||
| 17267 |
5/10✓ Branch 0 taken 4475203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4475201 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4475201 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4475202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4475201 times.
✗ Branch 9 not taken.
|
4475203 | if (std::search_n(primary->elements().begin(), primary->elements().end(), 1, |
| 17268 | 64313453 | c, [](const dd::Index_element *e, const dd::Column *c) { | |
| 17269 |
4/4✓ Branch 0 taken 5540617 times.
✓ Branch 1 taken 58772839 times.
✓ Branch 2 taken 719043 times.
✓ Branch 3 taken 4821573 times.
|
64313453 | return (!e->is_prefix() && &e->column() == c); |
| 17270 |
4/6✓ Branch 0 taken 4475201 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4475203 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3756158 times.
✓ Branch 5 taken 719044 times.
|
8950401 | }) == primary->elements().end()) { |
| 17271 |
1/2✓ Branch 0 taken 3756158 times.
✗ Branch 1 not taken.
|
3756158 | dd_add_hidden_element(primary, c); |
| 17272 | } | ||
| 17273 | } | ||
| 17274 | |||
| 17275 | 585253 | return 0; | |
| 17276 | 585286 | } | |
| 17277 | |||
| 17278 | /** Set Engine specific data to dd::Table object for upgrade. | ||
| 17279 | @param[in,out] thd thread handle | ||
| 17280 | @param[in] db_name database name | ||
| 17281 | @param[in] table_name table name | ||
| 17282 | @param[in,out] dd_table data dictionary cache object | ||
| 17283 | @return 0 on success, non-zero on failure */ | ||
| 17284 | 3975 | bool ha_innobase::upgrade_table(THD *thd, const char *db_name, | |
| 17285 | const char *table_name, dd::Table *dd_table) { | ||
| 17286 | 3975 | return (dd_upgrade_table(thd, db_name, table_name, dd_table, table)); | |
| 17287 | } | ||
| 17288 | |||
| 17289 | /** Get storage-engine private data for a data dictionary table. | ||
| 17290 | @param[in,out] dd_table data dictionary table definition | ||
| 17291 | @param reset reset counters | ||
| 17292 | @retval true an error occurred | ||
| 17293 | @retval false success */ | ||
| 17294 | 19008 | bool ha_innobase::get_se_private_data(dd::Table *dd_table, bool reset) { | |
| 17295 | static uint n_tables = 0; | ||
| 17296 | static uint n_indexes = 0; | ||
| 17297 | static uint n_pages = 4; | ||
| 17298 | |||
| 17299 | /* Reset counters on second create during upgrade. */ | ||
| 17300 |
2/2✓ Branch 0 taken 9669 times.
✓ Branch 1 taken 9339 times.
|
19008 | if (reset) { |
| 17301 | 9669 | n_tables = 0; | |
| 17302 | 9669 | n_indexes = 0; | |
| 17303 | 9669 | n_pages = 4; | |
| 17304 | // Also need to reset the set of DD table ids. | ||
| 17305 | 9669 | dict_sys_t::s_dd_table_ids.clear(); | |
| 17306 | } | ||
| 17307 | #ifdef UNIV_DEBUG | ||
| 17308 | 19008 | const uint n_indexes_old = n_indexes; | |
| 17309 | #endif | ||
| 17310 | |||
| 17311 |
1/2✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
|
19008 | DBUG_TRACE; |
| 17312 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19008 times.
|
19008 | assert(dd_table != nullptr); |
| 17313 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19008 times.
|
19008 | assert(n_tables < innodb_dd_table_size); |
| 17314 | |||
| 17315 |
3/6✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19008 times.
✗ Branch 5 not taken.
|
19008 | if ((*(const_cast<const dd::Table *>(dd_table))->columns().begin()) |
| 17316 |
3/4✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5094 times.
✓ Branch 3 taken 13914 times.
|
19008 | ->is_auto_increment()) { |
| 17317 |
2/4✓ Branch 0 taken 5094 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5094 times.
✗ Branch 3 not taken.
|
5094 | dd_set_autoinc(dd_table->se_private_data(), 0); |
| 17318 | } | ||
| 17319 | |||
| 17320 | #ifdef UNIV_DEBUG | ||
| 17321 | { | ||
| 17322 | /* These tables must not be partitioned. */ | ||
| 17323 |
2/4✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19008 times.
|
19008 | assert(dd_table->partitions()->empty()); |
| 17324 | } | ||
| 17325 | |||
| 17326 | 19008 | const innodb_dd_table_t &data = innodb_dd_table[n_tables]; | |
| 17327 | #endif | ||
| 17328 | |||
| 17329 |
2/4✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19008 times.
|
19008 | assert(dd_table->name() == data.name); |
| 17330 | |||
| 17331 |
1/2✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
|
19008 | dd_table->set_se_private_id(++n_tables); |
| 17332 |
1/2✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
|
19008 | dd_table->set_tablespace_id(dict_sys_t::s_dd_dict_space_id); |
| 17333 | |||
| 17334 | /* Set the table id for each column to be conform with the | ||
| 17335 | implementation in dd_write_table(). */ | ||
| 17336 |
6/10✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19008 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 154706 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 154706 times.
✓ Branch 9 taken 19008 times.
|
173714 | for (auto dd_column : *dd_table->table().columns()) { |
| 17337 |
3/6✓ Branch 0 taken 154706 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 154706 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 154706 times.
✗ Branch 5 not taken.
|
154706 | dd_column->se_private_data().set(dd_index_key_strings[DD_TABLE_ID], |
| 17338 | n_tables); | ||
| 17339 | } | ||
| 17340 | |||
| 17341 |
6/10✓ Branch 0 taken 19008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19008 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 38252 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 38252 times.
✓ Branch 9 taken 19008 times.
|
57260 | for (dd::Index *i : *dd_table->indexes()) { |
| 17342 |
1/2✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
|
38252 | i->set_tablespace_id(dict_sys_t::s_dd_dict_space_id); |
| 17343 | |||
| 17344 |
3/4✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 566 times.
✓ Branch 3 taken 37686 times.
|
38252 | if (fsp_is_inode_page(n_pages)) { |
| 17345 | 566 | ++n_pages; | |
| 17346 |
2/4✓ Branch 0 taken 566 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 566 times.
|
566 | ut_ad(!fsp_is_inode_page(n_pages)); |
| 17347 | } | ||
| 17348 | |||
| 17349 |
1/2✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
|
38252 | dd::Properties &p = i->se_private_data(); |
| 17350 | |||
| 17351 |
2/4✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
|
38252 | p.set(dd_index_key_strings[DD_INDEX_ROOT], n_pages++); |
| 17352 |
2/4✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
|
38252 | p.set(dd_index_key_strings[DD_INDEX_ID], ++n_indexes); |
| 17353 |
2/4✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
|
38252 | p.set(dd_index_key_strings[DD_INDEX_TRX_ID], 0); |
| 17354 |
2/4✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
|
38252 | p.set(dd_index_key_strings[DD_INDEX_SPACE_ID], dict_sys_t::s_dict_space_id); |
| 17355 |
2/4✓ Branch 0 taken 38252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38252 times.
✗ Branch 3 not taken.
|
38252 | p.set(dd_index_key_strings[DD_TABLE_ID], n_tables); |
| 17356 | } | ||
| 17357 | |||
| 17358 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19008 times.
|
19008 | assert(n_indexes - n_indexes_old == data.n_indexes); |
| 17359 | |||
| 17360 | 19008 | return false; | |
| 17361 | 19008 | } | |
| 17362 | |||
| 17363 | /** Create an InnoDB table. | ||
| 17364 | @param[in] name table name in filename-safe encoding | ||
| 17365 | @param[in] form table structure | ||
| 17366 | @param[in] create_info more information on the table | ||
| 17367 | @param[in,out] table_def dd::Table describing table to be | ||
| 17368 | created. Can be adjusted by SE, the changes will be saved into data-dictionary | ||
| 17369 | at statement commit time. | ||
| 17370 | @return error number | ||
| 17371 | @retval 0 on success */ | ||
| 17372 | 313713 | int ha_innobase::create(const char *name, TABLE *form, | |
| 17373 | HA_CREATE_INFO *create_info, dd::Table *table_def) { | ||
| 17374 | 313713 | THD *thd = ha_thd(); | |
| 17375 | |||
| 17376 | 313714 | adjust_encryption_options(create_info, table_def); | |
| 17377 | |||
| 17378 |
2/2✓ Branch 0 taken 10835 times.
✓ Branch 1 taken 302879 times.
|
313713 | if (thd_sql_command(thd) == SQLCOM_TRUNCATE) { |
| 17379 | 10835 | return (truncate_impl(name, form, table_def)); | |
| 17380 | } | ||
| 17381 | |||
| 17382 | 302879 | trx_t *trx = check_trx_exists(thd); | |
| 17383 | |||
| 17384 |
2/2✓ Branch 0 taken 149362 times.
✓ Branch 1 taken 153517 times.
|
302879 | if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { |
| 17385 | 149362 | innobase_register_trx(ht, thd, trx); | |
| 17386 | } | ||
| 17387 | |||
| 17388 | /* Determine if this CREATE TABLE will be making a file-per-table | ||
| 17389 | tablespace. Note that "srv_file_per_table" is not under | ||
| 17390 | dict_sys mutex protection, and could be changed while creating the | ||
| 17391 | table. So we read the current value here and make all further | ||
| 17392 | decisions based on this. */ | ||
| 17393 | 302879 | return (innobase_basic_ddl::create_impl(ha_thd(), name, form, create_info, | |
| 17394 | table_def, srv_file_per_table, true, | ||
| 17395 | 302863 | false, 0, 0, nullptr)); | |
| 17396 | } | ||
| 17397 | |||
| 17398 | /** Discards or imports an InnoDB tablespace. | ||
| 17399 | @param[in] discard true if discard, else import | ||
| 17400 | @param[in,out] table_def dd::Table describing table which | ||
| 17401 | tablespace is to be imported or discarded. Can be adjusted by SE, | ||
| 17402 | the changes will be saved into the data-dictionary at statement | ||
| 17403 | commit time. | ||
| 17404 | @return 0 == success, -1 == error */ | ||
| 17405 | |||
| 17406 | 1458 | int ha_innobase::discard_or_import_tablespace(bool discard, | |
| 17407 | dd::Table *table_def) { | ||
| 17408 |
1/2✓ Branch 0 taken 1458 times.
✗ Branch 1 not taken.
|
1458 | DBUG_TRACE; |
| 17409 | |||
| 17410 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1458 times.
|
1458 | ut_a(m_prebuilt->trx != nullptr); |
| 17411 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1458 times.
|
1458 | ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 17412 |
3/6✓ Branch 0 taken 1458 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1458 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1458 times.
|
1458 | ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 17413 | |||
| 17414 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1458 times.
|
1458 | if (high_level_read_only) { |
| 17415 | ✗ | return HA_ERR_TABLE_READONLY; | |
| 17416 | } | ||
| 17417 | |||
| 17418 | 1458 | dict_table_t *dict_table = m_prebuilt->table; | |
| 17419 | |||
| 17420 |
3/4✓ Branch 0 taken 1458 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1445 times.
|
1458 | if (dict_table->is_temporary()) { |
| 17421 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, |
| 17422 | ER_CANNOT_DISCARD_TEMPORARY_TABLE); | ||
| 17423 | |||
| 17424 | 13 | return HA_ERR_TABLE_NEEDS_UPGRADE; | |
| 17425 | } | ||
| 17426 | |||
| 17427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1445 times.
|
1445 | if (dict_table->space == TRX_SYS_SPACE) { |
| 17428 | ✗ | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 17429 | ER_TABLE_IN_SYSTEM_TABLESPACE, dict_table->name.m_name); | ||
| 17430 | |||
| 17431 | ✗ | return HA_ERR_TABLE_NEEDS_UPGRADE; | |
| 17432 | } | ||
| 17433 | |||
| 17434 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1443 times.
|
1445 | if (DICT_TF_HAS_SHARED_SPACE(dict_table->flags)) { |
| 17435 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | my_printf_error(ER_NOT_ALLOWED_COMMAND, |
| 17436 | "InnoDB: Cannot %s table `%s` because it is in" | ||
| 17437 | " a general tablespace. It must be file-per-table.", | ||
| 17438 | MYF(0), discard ? "discard" : "import", | ||
| 17439 | dict_table->name.m_name); | ||
| 17440 | |||
| 17441 | 2 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 17442 | } | ||
| 17443 | |||
| 17444 |
1/2✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
|
1443 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 17445 | |||
| 17446 |
2/4✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1443 times.
|
1443 | if (trx_in_innodb.is_aborted()) { |
| 17447 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 17448 | |||
| 17449 | ✗ | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 17450 | } | ||
| 17451 | |||
| 17452 |
1/2✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
|
1443 | trx_start_if_not_started(m_prebuilt->trx, true, UT_LOCATION_HERE); |
| 17453 | |||
| 17454 | /* Obtain an exclusive lock on the table. */ | ||
| 17455 |
2/2✓ Branch 0 taken 769 times.
✓ Branch 1 taken 674 times.
|
1443 | dberr_t err = row_mysql_lock_table( |
| 17456 |
1/2✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
|
1443 | m_prebuilt->trx, dict_table, LOCK_X, |
| 17457 | discard ? "setting table lock for DISCARD TABLESPACE" | ||
| 17458 | : "setting table lock for IMPORT TABLESPACE"); | ||
| 17459 | |||
| 17460 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1443 times.
|
1443 | if (err != DB_SUCCESS) { |
| 17461 | /* unable to lock the table: do nothing */ | ||
| 17462 | /* purecov: begin inspected */ | ||
| 17463 | ✗ | return convert_error_code_to_mysql(err, dict_table->flags, nullptr); | |
| 17464 | /* purecov: end */ | ||
| 17465 | } | ||
| 17466 | |||
| 17467 | /* Concurrent clone operation is not supported. */ | ||
| 17468 | Clone_notify notifier(Clone_notify::Type::SPACE_IMPORT, | ||
| 17469 |
1/2✓ Branch 0 taken 1443 times.
✗ Branch 1 not taken.
|
1443 | dict_sys_t::s_invalid_space_id, false); |
| 17470 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1441 times.
|
1443 | if (notifier.failed()) { |
| 17471 | 2 | return notifier.get_error(); | |
| 17472 | } | ||
| 17473 | |||
| 17474 |
2/2✓ Branch 0 taken 768 times.
✓ Branch 1 taken 673 times.
|
1441 | if (discard) { |
| 17475 | /* Discarding an already discarded tablespace should be an | ||
| 17476 | idempotent operation. Also, if the .ibd file is missing the | ||
| 17477 | user may want to set the DISCARD flag in order to IMPORT | ||
| 17478 | a new tablespace. */ | ||
| 17479 | |||
| 17480 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 750 times.
|
768 | if (dict_table->ibd_file_missing) { |
| 17481 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_WARN, |
| 17482 | ER_TABLESPACE_MISSING, dict_table->name.m_name); | ||
| 17483 | } | ||
| 17484 | |||
| 17485 | 766 | err = row_discard_tablespace_for_mysql(dict_table->name.m_name, | |
| 17486 |
1/2✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
|
768 | m_prebuilt->trx); |
| 17487 | |||
| 17488 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 668 times.
|
673 | } else if (!dict_table->ibd_file_missing) { |
| 17489 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
10 | ib::error(ER_IB_MSG_567) |
| 17490 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | << "Unable to import tablespace " << dict_table->name |
| 17491 | << " because it already" | ||
| 17492 | " exists. Please DISCARD the tablespace" | ||
| 17493 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | " before IMPORT."; |
| 17494 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, |
| 17495 | ER_TABLESPACE_EXISTS, dict_table->name.m_name); | ||
| 17496 | |||
| 17497 | 5 | return HA_ERR_TABLE_EXIST; | |
| 17498 | } else { | ||
| 17499 |
1/2✓ Branch 0 taken 662 times.
✗ Branch 1 not taken.
|
668 | err = row_import_for_mysql(dict_table, table_def, m_prebuilt); |
| 17500 | |||
| 17501 |
2/2✓ Branch 0 taken 516 times.
✓ Branch 1 taken 146 times.
|
662 | if (err == DB_SUCCESS) { |
| 17502 |
1/2✓ Branch 0 taken 516 times.
✗ Branch 1 not taken.
|
516 | info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE | |
| 17503 | HA_STATUS_AUTO); | ||
| 17504 | } | ||
| 17505 | } | ||
| 17506 | |||
| 17507 | /* Set the TABLESPACE DISCARD flag in the table definition | ||
| 17508 | on disk. */ | ||
| 17509 |
2/2✓ Branch 0 taken 1279 times.
✓ Branch 1 taken 149 times.
|
1428 | if (err == DB_SUCCESS) { |
| 17510 |
1/2✓ Branch 0 taken 1279 times.
✗ Branch 1 not taken.
|
1279 | dd_table_discard_tablespace(m_prebuilt->trx->mysql_thd, dict_table, |
| 17511 | table_def, discard); | ||
| 17512 | } | ||
| 17513 | |||
| 17514 |
6/6✓ Branch 0 taken 1279 times.
✓ Branch 1 taken 149 times.
✓ Branch 2 taken 516 times.
✓ Branch 3 taken 763 times.
✓ Branch 4 taken 515 times.
✓ Branch 5 taken 913 times.
|
1944 | if (err == DB_SUCCESS && !discard && |
| 17515 |
3/4✓ Branch 0 taken 516 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 515 times.
✓ Branch 3 taken 1 times.
|
516 | dict_stats_is_persistent_enabled(dict_table)) { |
| 17516 | dberr_t ret; | ||
| 17517 | |||
| 17518 | /* Adjust the persistent statistics. */ | ||
| 17519 |
1/2✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
|
515 | ret = dict_stats_update(dict_table, DICT_STATS_RECALC_PERSISTENT); |
| 17520 | |||
| 17521 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 515 times.
|
515 | if (ret != DB_SUCCESS) { |
| 17522 | ✗ | push_warning_printf(ha_thd(), Sql_condition::SL_WARNING, ER_ALTER_INFO, | |
| 17523 | "Error updating stats for table '%s'" | ||
| 17524 | " after table rebuild: %s", | ||
| 17525 | dict_table->name.m_name, ut_strerr(ret)); | ||
| 17526 | } | ||
| 17527 | } | ||
| 17528 | |||
| 17529 |
1/2✓ Branch 0 taken 1428 times.
✗ Branch 1 not taken.
|
1428 | return convert_error_code_to_mysql(err, dict_table->flags, nullptr); |
| 17530 | 1450 | } | |
| 17531 | |||
| 17532 | 10835 | int ha_innobase::truncate_impl(const char *name, TABLE *form, | |
| 17533 | dd::Table *table_def) { | ||
| 17534 |
1/2✓ Branch 0 taken 10835 times.
✗ Branch 1 not taken.
|
10835 | DBUG_TRACE; |
| 17535 | |||
| 17536 | /* Truncate of intrinsic table or hard-coded DD tables is not allowed | ||
| 17537 | for now. */ | ||
| 17538 |
2/4✓ Branch 0 taken 10835 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10835 times.
|
21670 | if (table_def == nullptr || |
| 17539 |
3/6✓ Branch 0 taken 10835 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10835 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10835 times.
|
10835 | dict_sys_t::is_dd_table_id(table_def->se_private_id())) { |
| 17540 | ✗ | my_error(ER_NOT_ALLOWED_COMMAND, MYF(0)); | |
| 17541 | ✗ | return HA_ERR_UNSUPPORTED; | |
| 17542 | } | ||
| 17543 | |||
| 17544 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10831 times.
|
10835 | if (high_level_read_only) { |
| 17545 | 4 | return HA_ERR_TABLE_READONLY; | |
| 17546 | } | ||
| 17547 | |||
| 17548 | char norm_name[FN_REFLEN]; | ||
| 17549 |
1/2✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
|
10831 | THD *thd = ha_thd(); |
| 17550 | 10831 | dict_table_t *innodb_table = nullptr; | |
| 17551 | 10831 | bool has_autoinc = false; | |
| 17552 | 10831 | int error = 0; | |
| 17553 |
1/2✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
|
10831 | const bool is_instant = dd_table_has_instant_cols(*table_def); |
| 17554 | |||
| 17555 |
2/4✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10831 times.
|
10831 | if (!normalize_table_name(norm_name, name)) { |
| 17556 | /* purecov: begin inspected */ | ||
| 17557 | ✗ | ut_d(ut_error); | |
| 17558 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 17559 | /* purecov: end */ | ||
| 17560 | } | ||
| 17561 | |||
| 17562 | innobase_truncate<dd::Table> truncator(thd, norm_name, form, table_def, false, | ||
| 17563 |
1/2✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
|
10831 | true); |
| 17564 | |||
| 17565 |
1/2✓ Branch 0 taken 10831 times.
✗ Branch 1 not taken.
|
10831 | error = truncator.open_table(innodb_table); |
| 17566 | |||
| 17567 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10831 times.
|
10831 | if (error != 0) { |
| 17568 | ✗ | return error; | |
| 17569 | } | ||
| 17570 | |||
| 17571 | 10831 | has_autoinc = dict_table_has_autoinc_col(innodb_table); | |
| 17572 | |||
| 17573 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10829 times.
|
10831 | if (dict_table_is_discarded(innodb_table)) { |
| 17574 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, norm_name); |
| 17575 | 2 | return HA_ERR_NO_SUCH_TABLE; | |
| 17576 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10827 times.
|
10829 | } else if (innodb_table->ibd_file_missing) { |
| 17577 | 2 | return innodb_table->keyring_encryption_info.page0_has_crypt_data == true | |
| 17578 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | ? HA_ERR_ENCRYPTION_KEY_MISSING |
| 17579 | 2 | : HA_ERR_TABLESPACE_MISSING; | |
| 17580 | } | ||
| 17581 | |||
| 17582 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10827 times.
|
10827 | if (UNIV_UNLIKELY(innodb_table->is_corrupt)) return HA_ERR_CRASHED; |
| 17583 | |||
| 17584 |
1/2✓ Branch 0 taken 10827 times.
✗ Branch 1 not taken.
|
10827 | trx_t *trx = check_trx_exists(thd); |
| 17585 |
1/2✓ Branch 0 taken 10827 times.
✗ Branch 1 not taken.
|
10827 | innobase_register_trx(ht, thd, trx); |
| 17586 | |||
| 17587 |
1/2✓ Branch 0 taken 10811 times.
✗ Branch 1 not taken.
|
10827 | error = truncator.exec(); |
| 17588 | |||
| 17589 |
2/2✓ Branch 0 taken 10806 times.
✓ Branch 1 taken 5 times.
|
10811 | if (error == 0) { |
| 17590 |
2/2✓ Branch 0 taken 380 times.
✓ Branch 1 taken 10426 times.
|
10806 | if (has_autoinc) { |
| 17591 |
2/4✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 380 times.
✗ Branch 3 not taken.
|
380 | dd_set_autoinc(table_def->se_private_data(), 0); |
| 17592 | } | ||
| 17593 | |||
| 17594 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 10798 times.
|
10806 | if (is_instant) { |
| 17595 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (dd_clear_instant_table(*table_def, true) != DB_SUCCESS) { |
| 17596 | ✗ | error = HA_ERR_GENERIC; | |
| 17597 | } | ||
| 17598 | } | ||
| 17599 | } | ||
| 17600 | |||
| 17601 | 10811 | return error; | |
| 17602 | 10819 | } | |
| 17603 | |||
| 17604 | /** Drop a table. | ||
| 17605 | @param[in] name table name | ||
| 17606 | @param[in] table_def dd::Table describing table to | ||
| 17607 | be dropped | ||
| 17608 | @return error number | ||
| 17609 | @retval 0 on success */ | ||
| 17610 | 272273 | int ha_innobase::delete_table(const char *name, const dd::Table *table_def) { | |
| 17611 |
4/4✓ Branch 0 taken 161299 times.
✓ Branch 1 taken 110974 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 272268 times.
|
433569 | if (table_def != nullptr && |
| 17612 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 161294 times.
|
161299 | dict_sys_t::is_dd_table_id(table_def->se_private_id())) { |
| 17613 | 2 | my_error(ER_NOT_ALLOWED_COMMAND, MYF(0)); | |
| 17614 | 2 | return (HA_ERR_UNSUPPORTED); | |
| 17615 | } | ||
| 17616 | |||
| 17617 | 272268 | THD *thd = ha_thd(); | |
| 17618 | 272271 | trx_t *trx = check_trx_exists(thd); | |
| 17619 | |||
| 17620 |
6/6✓ Branch 0 taken 161298 times.
✓ Branch 1 taken 110974 times.
✓ Branch 2 taken 118818 times.
✓ Branch 3 taken 42477 times.
✓ Branch 4 taken 118818 times.
✓ Branch 5 taken 153451 times.
|
272272 | if (table_def != nullptr && table_def->is_persistent()) { |
| 17621 | 118818 | innobase_register_trx(ht, thd, trx); | |
| 17622 | } | ||
| 17623 | |||
| 17624 | 272269 | return (innobase_basic_ddl::delete_impl(thd, name, table_def, nullptr)); | |
| 17625 | } | ||
| 17626 | |||
| 17627 | /** Validate the parameters in st_alter_tablespace | ||
| 17628 | before using them in InnoDB tablespace functions. | ||
| 17629 | @param[in] type Type os tablespace being validated | ||
| 17630 | @param[in] alter_info How to do the command. | ||
| 17631 | @return MySQL handler error code like HA_... */ | ||
| 17632 | 1310 | static int validate_create_tablespace_info(ib_file_suffix type, | |
| 17633 | st_alter_tablespace *alter_info) { | ||
| 17634 | /* The parser ensures that these fields are provided. */ | ||
| 17635 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
|
1310 | ut_a(alter_info->data_file_name != nullptr); |
| 17636 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
|
1310 | ut_a(alter_info->tablespace_name != nullptr); |
| 17637 | |||
| 17638 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
|
1310 | if (high_level_read_only) { |
| 17639 | ✗ | return (HA_ERR_INNODB_READ_ONLY); | |
| 17640 | } | ||
| 17641 | |||
| 17642 | /* Name validation should be ensured from the SQL layer. */ | ||
| 17643 |
2/4✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1310 times.
|
1310 | ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type, |
| 17644 | alter_info->tablespace_name)); | ||
| 17645 | |||
| 17646 | 1310 | int error = 0; | |
| 17647 | |||
| 17648 | /* Make sure the tablespace is not already open. */ | ||
| 17649 | |||
| 17650 | space_id_t space_id; | ||
| 17651 | |||
| 17652 |
1/2✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
|
1310 | space_id = fil_space_get_id_by_name(alter_info->tablespace_name); |
| 17653 | |||
| 17654 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
|
1310 | if (space_id != SPACE_UNKNOWN) { |
| 17655 | ✗ | my_printf_error(ER_TABLESPACE_EXISTS, | |
| 17656 | "InnoDB: A tablespace named `%s`" | ||
| 17657 | " already exists.", | ||
| 17658 | MYF(0), alter_info->tablespace_name); | ||
| 17659 | ✗ | error = HA_ERR_TABLESPACE_EXISTS; | |
| 17660 | } | ||
| 17661 | |||
| 17662 |
4/4✓ Branch 0 taken 952 times.
✓ Branch 1 taken 358 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 925 times.
|
1310 | if (type == IBD && alter_info->file_block_size) { |
| 17663 | /* Check for a bad file block size. */ | ||
| 17664 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 2 times.
|
27 | if (!ut_is_2pow(alter_info->file_block_size) || |
| 17665 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | alter_info->file_block_size < UNIV_ZIP_SIZE_MIN || |
| 17666 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | alter_info->file_block_size > UNIV_PAGE_SIZE_MAX) { |
| 17667 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 17668 | "InnoDB does not support" | ||
| 17669 | " FILE_BLOCK_SIZE=%llu", | ||
| 17670 | MYF(0), alter_info->file_block_size); | ||
| 17671 | 2 | error = HA_WRONG_CREATE_OPTION; | |
| 17672 | |||
| 17673 | /* Don't allow a file block size larger than UNIV_PAGE_SIZE. */ | ||
| 17674 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 21 times.
|
25 | } else if (alter_info->file_block_size > UNIV_PAGE_SIZE) { |
| 17675 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 17676 | "InnoDB: Cannot create a tablespace" | ||
| 17677 | " with FILE_BLOCK_SIZE=%llu because" | ||
| 17678 | " INNODB_PAGE_SIZE=%lu.", | ||
| 17679 | MYF(0), alter_info->file_block_size, UNIV_PAGE_SIZE); | ||
| 17680 | 4 | error = HA_WRONG_CREATE_OPTION; | |
| 17681 | |||
| 17682 | /* Don't allow a compressed tablespace when page size > 16k. */ | ||
| 17683 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | } else if (UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF && |
| 17684 | ✗ | alter_info->file_block_size != UNIV_PAGE_SIZE) { | |
| 17685 | ✗ | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 17686 | "InnoDB: Cannot create a COMPRESSED" | ||
| 17687 | " tablespace when innodb_page_size >" | ||
| 17688 | " 16k.", | ||
| 17689 | MYF(0)); | ||
| 17690 | ✗ | error = HA_WRONG_CREATE_OPTION; | |
| 17691 | } | ||
| 17692 | } | ||
| 17693 | |||
| 17694 | /* Validate AUTOEXTEND_SIZE clause. */ | ||
| 17695 | 1310 | if (alter_info->autoextend_size.has_value() && | |
| 17696 |
6/8✓ Branch 0 taken 43 times.
✓ Branch 1 taken 1267 times.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 1306 times.
|
1353 | alter_info->autoextend_size.value() > 0 && |
| 17697 |
4/6✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 39 times.
|
43 | validate_autoextend_size_value(alter_info->autoextend_size.value()) != |
| 17698 | DB_SUCCESS) { | ||
| 17699 | 4 | error = HA_WRONG_CREATE_OPTION; | |
| 17700 | } | ||
| 17701 | |||
| 17702 | /* Validate the ADD DATAFILE name. */ | ||
| 17703 |
1/2✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
|
1310 | std::string datafile_name(alter_info->data_file_name); |
| 17704 | |||
| 17705 | /* Undo Tablespace ADD DATAFILE filenames cannot be relative paths | ||
| 17706 | because it would be unclear what they are relative to. However, | ||
| 17707 | srv_undo_dir can be a relative directory. So evaluate this | ||
| 17708 | ADD DATAFILE value before it is appended to the undo dir. */ | ||
| 17709 |
7/8✓ Branch 0 taken 358 times.
✓ Branch 1 taken 952 times.
✓ Branch 2 taken 358 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 351 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 1303 times.
|
1310 | if (type == IBU && Fil_path::is_relative_path(datafile_name)) { |
| 17710 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_printf_error(ER_WRONG_FILE_NAME, |
| 17711 | "The ADD DATAFILE filepath for an UNDO TABLESPACE" | ||
| 17712 | " cannot be a relative path.", | ||
| 17713 | MYF(0)); | ||
| 17714 | |||
| 17715 | 7 | error = HA_ERR_WRONG_FILE_NAME; | |
| 17716 | } | ||
| 17717 | |||
| 17718 | /* If this is an undo tablespace basename and the innodb-undo-directory | ||
| 17719 | is not the datadir, then use an undo::Tablespace object to get the name | ||
| 17720 | since it will to attach a basename to the undo directory instead of the | ||
| 17721 | datadir. */ | ||
| 17722 |
2/2✓ Branch 0 taken 340 times.
✓ Branch 1 taken 18 times.
|
358 | if (alter_info->ts_cmd_type == CREATE_UNDO_TABLESPACE && |
| 17723 |
4/4✓ Branch 0 taken 358 times.
✓ Branch 1 taken 952 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1308 times.
|
1668 | std::string::npos == datafile_name.find_first_of(Fil_path::SEPARATOR) && |
| 17724 |
3/4✓ Branch 0 taken 340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 338 times.
|
340 | !MySQL_undo_path.is_same_as(MySQL_datadir_path)) { |
| 17725 | 2 | undo::Tablespace undo_space(0); | |
| 17726 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | undo_space.set_file_name(datafile_name.c_str()); |
| 17727 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | datafile_name = undo_space.file_name(); |
| 17728 | 2 | } | |
| 17729 | |||
| 17730 |
1/2✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
|
1310 | Fil_path filepath(datafile_name, true); |
| 17731 | |||
| 17732 | /* If this path contains a circular section such as "/anydir/../" then | ||
| 17733 | reject it since if that unnecessary directory reference is deleted | ||
| 17734 | the path will not be useaable on Linux. */ | ||
| 17735 |
3/4✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1301 times.
|
1310 | if (filepath.is_circular()) { |
| 17736 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | my_printf_error(ER_WRONG_FILE_NAME, |
| 17737 | "The ADD DATAFILE filepath cannot contain circular " | ||
| 17738 | "directory references.", | ||
| 17739 | MYF(0)); | ||
| 17740 | 9 | error = HA_ERR_WRONG_FILE_NAME; | |
| 17741 | } | ||
| 17742 | |||
| 17743 | #ifndef _WIN32 | ||
| 17744 | /* On Non-Windows platforms, '\\' is a valid file name character. | ||
| 17745 | But for InnoDB datafiles, we always assume it is a directory | ||
| 17746 | separator and convert these to '/' */ | ||
| 17747 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1310 times.
|
1310 | if (strchr(filepath, '\\') != nullptr) { |
| 17748 | ✗ | ib::warn(ER_IB_MSG_568) << "Converting backslash to forward slash in" | |
| 17749 | ✗ | " ADD DATAFILE " | |
| 17750 | ✗ | << filepath.path(); | |
| 17751 | } | ||
| 17752 | #endif /* _WIN32 */ | ||
| 17753 | |||
| 17754 | /* The filepath must end with a valid suffix and contain a basename of at | ||
| 17755 | least 1 character before the suffix. */ | ||
| 17756 |
1/2✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
|
1310 | size_t dirname_len = dirname_length(filepath); |
| 17757 | 1310 | const char *basename = filepath + dirname_len; | |
| 17758 | 1310 | auto basename_len = strlen(basename); | |
| 17759 | |||
| 17760 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1303 times.
|
1310 | if (basename_len <= 4) { |
| 17761 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_printf_error( |
| 17762 | ER_WRONG_FILE_NAME, | ||
| 17763 | "The ADD DATAFILE filepath does not have a proper filename.", MYF(0)); | ||
| 17764 | 7 | error = HA_ERR_WRONG_FILE_NAME; | |
| 17765 | } | ||
| 17766 | |||
| 17767 |
4/6✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1310 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1304 times.
|
1310 | if (!Fil_path::has_suffix(type, basename)) { |
| 17768 | 6 | my_printf_error(ER_WRONG_FILE_NAME, | |
| 17769 | "The ADD DATAFILE filepath must end with '%s'.", MYF(0), | ||
| 17770 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | dot_ext[type]); |
| 17771 | 6 | error = HA_ERR_WRONG_FILE_NAME; | |
| 17772 | } | ||
| 17773 | |||
| 17774 |
3/4✓ Branch 0 taken 1310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1308 times.
|
1310 | if (!filepath.is_valid()) { |
| 17775 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_WRONG_FILE_NAME, MYF(0), filepath.path().c_str()); |
| 17776 | |||
| 17777 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_WRONG_FILE_NAME, "Invalid use of ':'.", MYF(0)); |
| 17778 | |||
| 17779 | 2 | return (HA_ERR_WRONG_FILE_NAME); | |
| 17780 | } | ||
| 17781 | |||
| 17782 | /* If this file already exists, we cannot use this filename. */ | ||
| 17783 |
3/4✓ Branch 0 taken 1308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1304 times.
|
1308 | if (os_file_exists(filepath.path().c_str())) { |
| 17784 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | my_printf_error(ER_WRONG_FILE_NAME, |
| 17785 | "The ADD DATAFILE filepath already exists.", MYF(0)); | ||
| 17786 | 4 | error = HA_ERR_WRONG_FILE_NAME; | |
| 17787 | } | ||
| 17788 | |||
| 17789 | 78 | Fil_path dirpath((dirname_len == 0 ? "." : datafile_name.c_str()), | |
| 17790 |
5/6✓ Branch 0 taken 78 times.
✓ Branch 1 taken 1230 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 1230 times.
✓ Branch 4 taken 1308 times.
✗ Branch 5 not taken.
|
1386 | (dirname_len == 0 ? 1 : dirname_len), true); |
| 17791 | |||
| 17792 |
3/4✓ Branch 0 taken 1308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1302 times.
|
1308 | if (!dirpath.is_directory_and_exists()) { |
| 17793 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | ib::error(ER_IB_MSG_WRONG_TABLESPACE_DIR, alter_info->tablespace_name); |
| 17794 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_printf_error(ER_WRONG_FILE_NAME, |
| 17795 | "The directory does not exist or is incorrect.", MYF(0)); | ||
| 17796 | |||
| 17797 | 6 | error = HA_ERR_WRONG_FILE_NAME; | |
| 17798 | } | ||
| 17799 | |||
| 17800 | /* Do not allow the file to be created in a unique undo directory. */ | ||
| 17801 |
6/6✓ Branch 0 taken 950 times.
✓ Branch 1 taken 358 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 944 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1307 times.
|
1314 | if (type == IBD && MySQL_undo_path_is_unique && |
| 17802 |
3/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 times.
|
6 | (MySQL_undo_path.is_same_as(dirpath) || |
| 17803 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
|
5 | MySQL_undo_path.is_ancestor(dirpath))) { |
| 17804 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | std::string msg("The DATAFILE location cannot be the undo directory."); |
| 17805 | |||
| 17806 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str()); |
| 17807 | |||
| 17808 | 1 | ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE, | |
| 17809 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | alter_info->tablespace_name, msg.c_str()); |
| 17810 | |||
| 17811 | 1 | error = HA_ERR_WRONG_FILE_NAME; | |
| 17812 | 1 | } | |
| 17813 | |||
| 17814 | /* General tablespaces can be inside but not under the datadir | ||
| 17815 | since those directories contain datafiles for specific schemas.*/ | ||
| 17816 |
7/8✓ Branch 0 taken 950 times.
✓ Branch 1 taken 358 times.
✓ Branch 2 taken 950 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 943 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 1301 times.
|
1308 | if (type == IBD && MySQL_datadir_path.is_ancestor(dirpath)) { |
| 17817 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | std::string msg("The DATAFILE location cannot be under the datadir."); |
| 17818 | |||
| 17819 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str()); |
| 17820 | |||
| 17821 | 7 | ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE, | |
| 17822 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | alter_info->tablespace_name, msg.c_str()); |
| 17823 | |||
| 17824 | 7 | error = HA_ERR_WRONG_FILE_NAME; | |
| 17825 | 7 | } | |
| 17826 | |||
| 17827 | /* Validate the tablespace location. */ | ||
| 17828 |
3/4✓ Branch 0 taken 1308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1301 times.
✓ Branch 3 taken 7 times.
|
2609 | bool in_datadir = MySQL_datadir_path.is_ancestor(dirpath) || |
| 17829 |
3/4✓ Branch 0 taken 1301 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1251 times.
✓ Branch 3 taken 50 times.
|
1301 | MySQL_datadir_path.is_same_as(dirpath); |
| 17830 | bool in_known_location = | ||
| 17831 |
3/4✓ Branch 0 taken 1258 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
1308 | in_datadir ? true : fil_path_is_known(dirpath.path()); |
| 17832 | |||
| 17833 | /* All undo and general tablespaces must be in known directories */ | ||
| 17834 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1288 times.
|
1308 | if (!in_known_location) { |
| 17835 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | std::string msg("The "); |
| 17836 |
3/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
20 | msg += (type == IBU ? "UNDO " : ""); |
| 17837 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | msg += "DATAFILE location must be in a known directory."; |
| 17838 | |||
| 17839 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str()); |
| 17840 | |||
| 17841 | 20 | ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE, | |
| 17842 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | alter_info->tablespace_name, msg.c_str()); |
| 17843 | |||
| 17844 | 20 | error = HA_ERR_WRONG_FILE_NAME; | |
| 17845 | 20 | } | |
| 17846 | |||
| 17847 | 1308 | return (error); | |
| 17848 | 1310 | } | |
| 17849 | |||
| 17850 | /** CREATE a tablespace. | ||
| 17851 | @param[in] hton Handlerton of InnoDB | ||
| 17852 | @param[in] thd Connection | ||
| 17853 | @param[in] alter_info How to do the command | ||
| 17854 | @param[in,out] dd_space Tablespace metadata | ||
| 17855 | @return MySQL error code*/ | ||
| 17856 | 952 | static int innodb_create_tablespace(handlerton *hton, THD *thd, | |
| 17857 | st_alter_tablespace *alter_info, | ||
| 17858 | dd::Tablespace *dd_space) { | ||
| 17859 | int error; | ||
| 17860 |
1/2✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
|
952 | Tablespace tablespace; |
| 17861 | 952 | uint32_t fsp_flags = 0; | |
| 17862 | 952 | fil_encryption_t keyring_encryption_mode{FIL_ENCRYPTION_DEFAULT}; | |
| 17863 | |||
| 17864 |
1/2✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
|
952 | DBUG_TRACE; |
| 17865 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 952 times.
|
952 | assert(hton == innodb_hton_ptr); |
| 17866 | |||
| 17867 |
2/4✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 952 times.
|
952 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 17868 |
2/4✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 952 times.
|
952 | ut_ad(strcmp(alter_info->data_file_name, |
| 17869 | dd_tablespace_get_filename(dd_space)) == 0); | ||
| 17870 | |||
| 17871 | /* Be sure the input parameters are valid before continuing. */ | ||
| 17872 |
1/2✓ Branch 0 taken 952 times.
✗ Branch 1 not taken.
|
952 | error = validate_create_tablespace_info(IBD, alter_info); |
| 17873 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 909 times.
|
952 | if (error) { |
| 17874 | 43 | return error; | |
| 17875 | } | ||
| 17876 | |||
| 17877 | /* Create the tablespace object. */ | ||
| 17878 |
1/2✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
|
909 | tablespace.set_name(alter_info->tablespace_name); |
| 17879 | |||
| 17880 |
1/2✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
|
909 | dberr_t err = tablespace.add_datafile(alter_info->data_file_name); |
| 17881 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 909 times.
|
909 | if (err != DB_SUCCESS) { |
| 17882 | ✗ | return convert_error_code_to_mysql(err, 0, nullptr); | |
| 17883 | } | ||
| 17884 | |||
| 17885 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 870 times.
|
948 | tablespace.set_autoextend_size(alter_info->autoextend_size.has_value() |
| 17886 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | ? alter_info->autoextend_size.value() |
| 17887 | : 0); | ||
| 17888 | |||
| 17889 | /* Get the transaction associated with the current thd. */ | ||
| 17890 |
1/2✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
|
909 | trx_t *trx = check_trx_exists(thd); |
| 17891 |
1/2✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
|
909 | TrxInInnoDB trx_in_innodb(trx); |
| 17892 |
1/2✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
|
909 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 17893 | 909 | ++trx->will_lock; | |
| 17894 | |||
| 17895 |
1/2✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
|
909 | row_mysql_lock_data_dictionary(trx, UT_LOCATION_HERE); |
| 17896 | |||
| 17897 | /* In FSP_FLAGS, a zip_ssize of zero means that the tablespace | ||
| 17898 | holds non-compresssed tables. A non-zero zip_ssize means that | ||
| 17899 | the general tablespace can ONLY contain compressed tables. */ | ||
| 17900 | 909 | uint32_t zip_size = static_cast<uint32_t>(alter_info->file_block_size); | |
| 17901 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 909 times.
|
909 | ut_ad(zip_size <= UNIV_PAGE_SIZE_MAX); |
| 17902 |
2/2✓ Branch 0 taken 888 times.
✓ Branch 1 taken 21 times.
|
909 | if (zip_size == 0) { |
| 17903 | 888 | zip_size = UNIV_PAGE_SIZE; | |
| 17904 | } | ||
| 17905 | 909 | bool zipped = (zip_size != UNIV_PAGE_SIZE); | |
| 17906 |
1/2✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
|
909 | page_size_t page_size(zip_size, UNIV_PAGE_SIZE, zipped); |
| 17907 | 909 | bool atomic_blobs = page_size.is_compressed(); | |
| 17908 | 909 | KeyringEncryptionKeyIdInfo keyring_encryption_key_id; | |
| 17909 | 909 | bool encrypted = false; | |
| 17910 | 909 | dd::String_type encrypt; | |
| 17911 |
4/8✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 909 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 909 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 909 times.
✗ Branch 7 not taken.
|
909 | if (dd_space->options().exists("encryption")) { |
| 17912 |
3/6✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 909 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 909 times.
✗ Branch 5 not taken.
|
909 | (void)dd_space->options().get("encryption", &encrypt); |
| 17913 | |||
| 17914 | /* Validate Encryption option provided */ | ||
| 17915 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 889 times.
|
909 | if (Encryption::validate_for_tablespace(encrypt.c_str()) != DB_SUCCESS) { |
| 17916 | /* Incorrect encryption option */ | ||
| 17917 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); |
| 17918 | 20 | err = DB_UNSUPPORTED; | |
| 17919 | 22 | goto error_exit; | |
| 17920 | } | ||
| 17921 | |||
| 17922 | 889 | bool explicit_encryption{false}; | |
| 17923 |
4/8✓ Branch 0 taken 889 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 889 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 889 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 889 times.
✗ Branch 7 not taken.
|
889 | if (dd_space->options().exists("explicit_encryption")) { |
| 17924 |
3/6✓ Branch 0 taken 889 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 889 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 889 times.
✗ Branch 5 not taken.
|
889 | (void)dd_space->options().get("explicit_encryption", |
| 17925 | &explicit_encryption); | ||
| 17926 | } | ||
| 17927 | /* Validate that encryption is not MK encryption if online encryption is ON. | ||
| 17928 | encrypt_type is set to Y for both MK encryption and ONLINE_TO_KEYRING | ||
| 17929 | encryption. However, when d_t_e=ONLINE_TO_KEYRING is set it is only | ||
| 17930 | possible to specify MK encryption by explicitly specifying | ||
| 17931 | ENCRYPTION='Y'. We use this information here. | ||
| 17932 | */ | ||
| 17933 |
2/2✓ Branch 0 taken 272 times.
✓ Branch 1 taken 24 times.
|
1185 | if (Encryption::is_master_key_encryption(encrypt.c_str()) && |
| 17934 |
4/6✓ Branch 0 taken 296 times.
✓ Branch 1 taken 593 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 272 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 889 times.
|
1185 | explicit_encryption && Encryption::is_online_encryption_on()) { |
| 17935 | ✗ | my_printf_error( | |
| 17936 | ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION, | ||
| 17937 | "InnoDB: ENCRYPTED='Y' not supported for tablespace because " | ||
| 17938 | "online encryption to KEYRING is turned ON.", | ||
| 17939 | MYF(0)); | ||
| 17940 | ✗ | err = DB_UNSUPPORTED; | |
| 17941 | ✗ | goto error_exit; | |
| 17942 | } | ||
| 17943 | |||
| 17944 | /* If encryption is to be done */ | ||
| 17945 |
2/2✓ Branch 0 taken 296 times.
✓ Branch 1 taken 593 times.
|
889 | if (!Encryption::is_none(encrypt.c_str())) { |
| 17946 | /* Check if keyring is ready. */ | ||
| 17947 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 294 times.
|
296 | if (!Encryption::check_keyring()) { |
| 17948 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 17949 | 2 | err = DB_UNSUPPORTED; | |
| 17950 | 2 | goto error_exit; | |
| 17951 | } | ||
| 17952 | 294 | encrypted = true; | |
| 17953 | } | ||
| 17954 | |||
| 17955 |
4/6✓ Branch 0 taken 887 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 885 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
887 | DBUG_EXECUTE_IF("ib_crash_during_create_tablespace_for_encryption", |
| 17956 | DBUG_SUICIDE();); | ||
| 17957 | } | ||
| 17958 | |||
| 17959 | /* Create the filespace flags */ | ||
| 17960 | 885 | fsp_flags = | |
| 17961 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | fsp_flags_init(page_size, /* page sizes and a flag if compressed */ |
| 17962 | atomic_blobs, /* needed only for compressed tables */ | ||
| 17963 | false, /* This is not a file-per-table tablespace */ | ||
| 17964 | true, /* This is a general shared tablespace */ | ||
| 17965 | false, /* Temporary General Tablespaces not allowed */ | ||
| 17966 | encrypted); /* If tablespace is to be Encrypted */ | ||
| 17967 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | tablespace.set_flags(fsp_flags); |
| 17968 | |||
| 17969 | 1770 | keyring_encryption_key_id = { | |
| 17970 | 885 | alter_info->encryption_key_id.was_encryption_key_id_set, | |
| 17971 | alter_info->encryption_key_id.id}; | ||
| 17972 | |||
| 17973 | keyring_encryption_mode = | ||
| 17974 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | get_encryption_mode(encrypt.c_str(), alter_info->explicit_encryption); |
| 17975 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 885 times.
|
885 | ut_ad(keyring_encryption_mode != FIL_ENCRYPTION_ON); |
| 17976 | |||
| 17977 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | err = dict_build_tablespace(trx, &tablespace, keyring_encryption_mode, |
| 17978 | keyring_encryption_key_id); | ||
| 17979 | |||
| 17980 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 882 times.
|
885 | if (err == DB_SUCCESS) { |
| 17981 | /* Update the fil_space_t with autoextend_size value. */ | ||
| 17982 |
1/2✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
|
882 | fil_set_autoextend_size(tablespace.space_id(), |
| 17983 | tablespace.get_autoextend_size()); | ||
| 17984 | |||
| 17985 |
1/2✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
|
882 | err = btr_sdi_create_index(tablespace.space_id(), true); |
| 17986 |
1/2✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
|
882 | if (err == DB_SUCCESS) { |
| 17987 | 882 | fsp_flags_set_sdi(fsp_flags); | |
| 17988 |
1/2✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
|
882 | tablespace.set_flags(fsp_flags); |
| 17989 | |||
| 17990 | /* Make sure the DD has the space_id and the flags. */ | ||
| 17991 |
1/2✓ Branch 0 taken 882 times.
✗ Branch 1 not taken.
|
882 | dd_write_tablespace(dd_space, tablespace.space_id(), tablespace.flags(), |
| 17992 | DD_SPACE_STATE_NORMAL); | ||
| 17993 | } | ||
| 17994 | } | ||
| 17995 | |||
| 17996 | 3 | error_exit: | |
| 17997 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 882 times.
|
907 | if (err != DB_SUCCESS) { |
| 17998 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | error = convert_error_code_to_mysql(err, 0, nullptr); |
| 17999 | } | ||
| 18000 | |||
| 18001 |
1/2✓ Branch 0 taken 907 times.
✗ Branch 1 not taken.
|
907 | row_mysql_unlock_data_dictionary(trx); |
| 18002 | |||
| 18003 | 907 | return error; | |
| 18004 | 950 | } | |
| 18005 | |||
| 18006 | /** Alter AUTOEXTEND_SIZE a tablespace. | ||
| 18007 | @param[in] hton Handlerton of InnoDB | ||
| 18008 | @param[in] alter_info How to do the command | ||
| 18009 | @param[in] old_dd_space Tablespace metadata | ||
| 18010 | @return MySQL error code */ | ||
| 18011 | 5018 | static int innobase_alter_autoextend_size_tablespace( | |
| 18012 | handlerton *hton, st_alter_tablespace *alter_info, | ||
| 18013 | const dd::Tablespace *old_dd_space) { | ||
| 18014 | 5018 | space_id_t space_id = SPACE_UNKNOWN; | |
| 18015 | |||
| 18016 |
1/2✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
|
5018 | DBUG_TRACE; |
| 18017 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
|
5018 | assert(hton == innodb_hton_ptr); |
| 18018 | |||
| 18019 |
3/6✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5018 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5018 times.
✗ Branch 5 not taken.
|
5018 | DEBUG_SYNC(current_thd, "innodb_alter_autoextend_size_tablespace"); |
| 18020 | |||
| 18021 |
2/4✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5018 times.
|
5018 | ut_ad(alter_info->tablespace_name == old_dd_space->name()); |
| 18022 | |||
| 18023 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
|
5018 | if (srv_read_only_mode) { |
| 18024 | ✗ | return HA_ERR_INNODB_READ_ONLY; | |
| 18025 | } | ||
| 18026 | |||
| 18027 | /* Validate the name */ | ||
| 18028 |
2/4✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5018 times.
|
5018 | ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type, |
| 18029 | alter_info->tablespace_name)); | ||
| 18030 | |||
| 18031 | /* Be sure that this tablespace is known and valid. */ | ||
| 18032 |
2/6✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5018 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
10036 | if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 18033 |
4/8✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5018 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5018 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5018 times.
✗ Branch 7 not taken.
|
15054 | &space_id) || |
| 18034 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
|
5018 | space_id == SPACE_UNKNOWN) { |
| 18035 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 18036 | } | ||
| 18037 | |||
| 18038 | /* Make sure tablespace is loaded. */ | ||
| 18039 |
1/2✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
|
5018 | fil_space_t *space = fil_space_acquire(space_id); |
| 18040 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
|
5018 | if (space == nullptr) { |
| 18041 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 18042 | } | ||
| 18043 |
2/4✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5018 times.
|
5018 | ut_ad(fsp_flags_is_valid(space->flags)); |
| 18044 | |||
| 18045 | /* Validate the autoextend_size value. */ | ||
| 18046 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5018 times.
|
5018 | ut_ad(alter_info->autoextend_size.has_value()); |
| 18047 | |||
| 18048 |
1/2✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
|
5018 | uint64_t autoextend_size = alter_info->autoextend_size.value(); |
| 18049 | |||
| 18050 |
2/2✓ Branch 0 taken 5009 times.
✓ Branch 1 taken 9 times.
|
5018 | if (autoextend_size > 0) { |
| 18051 |
1/2✓ Branch 0 taken 5009 times.
✗ Branch 1 not taken.
|
5009 | int ret = validate_autoextend_size_value(autoextend_size); |
| 18052 | |||
| 18053 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5007 times.
|
5009 | if (ret != DB_SUCCESS) { |
| 18054 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | fil_space_release(space); |
| 18055 | 2 | return ret; | |
| 18056 | } | ||
| 18057 | } | ||
| 18058 | |||
| 18059 |
2/4✓ Branch 0 taken 5016 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5016 times.
✗ Branch 3 not taken.
|
5016 | fil_set_autoextend_size(space_id, alter_info->autoextend_size.value()); |
| 18060 | |||
| 18061 |
1/2✓ Branch 0 taken 5016 times.
✗ Branch 1 not taken.
|
5016 | fil_space_release(space); |
| 18062 | |||
| 18063 | 5016 | return 0; | |
| 18064 | 5018 | } | |
| 18065 | |||
| 18066 | /** | ||
| 18067 | Return data filename extension for a InnoDB tablespace. | ||
| 18068 | */ | ||
| 18069 | |||
| 18070 | 134 | static const char *innobase_get_tablespace_filename_ext() { return ".ibd"; } | |
| 18071 | |||
| 18072 | /** Alter Encrypt/Unencrypt a tablespace. | ||
| 18073 | @param[in] hton Handlerton of InnoDB | ||
| 18074 | @param[in] thd Connection | ||
| 18075 | @param[in] alter_info How to do the command | ||
| 18076 | @param[in] old_dd_space Tablespace metadata | ||
| 18077 | @param[in,out] new_dd_space Tablespace metadata | ||
| 18078 | @return MySQL error code*/ | ||
| 18079 | 483 | static int innobase_alter_encrypt_tablespace(handlerton *hton, THD *thd, | |
| 18080 | st_alter_tablespace *alter_info, | ||
| 18081 | const dd::Tablespace *old_dd_space, | ||
| 18082 | dd::Tablespace *new_dd_space) { | ||
| 18083 | 483 | trx_t *trx = nullptr; | |
| 18084 | 483 | dberr_t err = DB_SUCCESS; | |
| 18085 | 483 | int error = 0; | |
| 18086 | 483 | space_id_t space_id = SPACE_UNKNOWN; | |
| 18087 | |||
| 18088 |
1/2✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
|
483 | DBUG_TRACE; |
| 18089 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
|
483 | assert(hton == innodb_hton_ptr); |
| 18090 | |||
| 18091 |
4/6✓ Branch 0 taken 457 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 457 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 457 times.
✗ Branch 5 not taken.
|
483 | DEBUG_SYNC(current_thd, "innodb_alter_encrypt_tablespace"); |
| 18092 | |||
| 18093 |
2/4✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 483 times.
|
483 | ut_ad(alter_info->tablespace_name == old_dd_space->name()); |
| 18094 | |||
| 18095 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
|
483 | if (srv_read_only_mode) { |
| 18096 | ✗ | return HA_ERR_INNODB_READ_ONLY; | |
| 18097 | } | ||
| 18098 | |||
| 18099 | /* Name validation should be ensured from the SQL layer. */ | ||
| 18100 |
2/4✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 483 times.
|
483 | ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type, |
| 18101 | alter_info->tablespace_name)); | ||
| 18102 | |||
| 18103 | /* Be sure that this tablespace is known and valid. */ | ||
| 18104 |
2/6✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 483 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
966 | if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 18105 |
4/8✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 483 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 483 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 483 times.
✗ Branch 7 not taken.
|
1449 | &space_id) || |
| 18106 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
|
483 | space_id == SPACE_UNKNOWN) { |
| 18107 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 18108 | } | ||
| 18109 | |||
| 18110 | /* Make sure keyring plugin is loaded. */ | ||
| 18111 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 467 times.
|
483 | if (!Encryption::check_keyring()) { |
| 18112 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 18113 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | error = convert_error_code_to_mysql(DB_ERROR, 0, nullptr); |
| 18114 | 16 | return error; | |
| 18115 | } | ||
| 18116 | |||
| 18117 | /* Make sure tablespace is loaded. */ | ||
| 18118 |
1/2✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
|
467 | fil_space_t *space = fil_space_get(space_id); |
| 18119 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
|
467 | if (space == nullptr) { |
| 18120 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 18121 | } | ||
| 18122 |
2/4✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 467 times.
|
467 | ut_ad(fsp_flags_is_valid(space->flags)); |
| 18123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
|
467 | ut_ad(FSP_FLAGS_GET_SHARED(space->flags)); |
| 18124 | |||
| 18125 |
1/2✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
|
467 | const dd::Properties &oldopts = old_dd_space->options(); |
| 18126 |
1/2✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
|
467 | const dd::Properties &newopts = new_dd_space->options(); |
| 18127 | |||
| 18128 | /* Get value of old encryption option. */ | ||
| 18129 | 467 | dd::String_type oldenc; | |
| 18130 |
3/6✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 467 times.
✗ Branch 5 not taken.
|
467 | if (oldopts.exists("encryption")) { |
| 18131 |
2/4✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
|
467 | (void)oldopts.get("encryption", &oldenc); |
| 18132 | } | ||
| 18133 | |||
| 18134 | /* Get value of new encryption option. */ | ||
| 18135 |
3/6✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 467 times.
|
467 | ut_ad(newopts.exists("encryption")); |
| 18136 | 467 | dd::String_type newenc; | |
| 18137 |
2/4✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
|
467 | (void)newopts.get("encryption", &newenc); |
| 18138 | |||
| 18139 | /* Validate new encryption option provided */ | ||
| 18140 | 467 | const char *encrypt = newenc.data(); | |
| 18141 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 421 times.
|
467 | if (Encryption::validate_for_tablespace(encrypt) != DB_SUCCESS) { |
| 18142 | /* Incorrect encryption option */ | ||
| 18143 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); |
| 18144 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | error = convert_error_code_to_mysql(DB_ERROR, 0, nullptr); |
| 18145 | 46 | return error; | |
| 18146 | } | ||
| 18147 | |||
| 18148 | /* If old tablespace definition says it's encrypted */ | ||
| 18149 | bool is_old_encrypted = | ||
| 18150 |
3/4✓ Branch 0 taken 421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 208 times.
✓ Branch 3 taken 213 times.
|
421 | !(oldenc.empty() || Encryption::is_none(oldenc.data())); |
| 18151 | /* If new tablespace definition says it's encrypted */ | ||
| 18152 | 421 | bool is_new_encrypted = !Encryption::is_none(newenc.data()); | |
| 18153 | 421 | fil_space_crypt_t *crypt_data = space->crypt_data; | |
| 18154 | |||
| 18155 | 421 | bool to_encrypt = false; | |
| 18156 | // It is only possible to mark tablespace to be skipped by encryption threads | ||
| 18157 | // if it is not already encrypted. | ||
| 18158 |
4/4✓ Branch 0 taken 213 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 160 times.
|
421 | if (!is_old_encrypted && !is_new_encrypted && |
| 18159 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
53 | alter_info->explicit_encryption) { |
| 18160 |
2/4✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
|
53 | if (!fil_crypt_exclude_tablespace_from_rotation_permanently(space)) { |
| 18161 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 18162 | } | ||
| 18163 | 53 | return error; | |
| 18164 |
3/4✓ Branch 0 taken 160 times.
✓ Branch 1 taken 208 times.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
|
368 | } else if (!is_old_encrypted && is_new_encrypted) { |
| 18165 |
3/4✓ Branch 0 taken 148 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
|
160 | DEBUG_SYNC_C("alter_encryption_to_y"); |
| 18166 |
2/4✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 160 times.
|
160 | if (!fil_crypt_exclude_tablespace_from_rotation_temporarily(space)) { |
| 18167 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 18168 | } | ||
| 18169 |
3/4✓ Branch 0 taken 148 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
|
160 | DEBUG_SYNC_C("alter_encryption_to_y_tablespace_excluded"); |
| 18170 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 144 times.
|
160 | if (crypt_data != nullptr) { |
| 18171 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | mutex_enter(&crypt_data->mutex); |
| 18172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | ut_ad(crypt_data->type == CRYPT_SCHEME_UNENCRYPTED); |
| 18173 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | ut_ad(crypt_data->min_key_version == |
| 18174 | ENCRYPTION_KEY_VERSION_NOT_ENCRYPTED); | ||
| 18175 | // setting it to default - it could have been FIL_ENCRYPTION_N | ||
| 18176 | // however, now that it gets encrypted with Master Key encryption | ||
| 18177 | // the user will have a chance to re-encrypt it with KEYRING | ||
| 18178 | 16 | crypt_data->encryption = FIL_ENCRYPTION_DEFAULT; | |
| 18179 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | mutex_exit(&space->crypt_data->mutex); |
| 18180 | } | ||
| 18181 | /* Encrypt tablespace */ | ||
| 18182 | 160 | to_encrypt = true; | |
| 18183 |
3/4✓ Branch 0 taken 208 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 145 times.
✓ Branch 3 taken 63 times.
|
208 | } else if (is_old_encrypted && !is_new_encrypted) { |
| 18184 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 133 times.
|
145 | if (crypt_data) { |
| 18185 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | mutex_enter(&crypt_data->mutex); |
| 18186 | 12 | bool is_keyring_encrypted{crypt_data->type != CRYPT_SCHEME_UNENCRYPTED}; | |
| 18187 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | mutex_exit(&crypt_data->mutex); |
| 18188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (is_keyring_encrypted) { |
| 18189 | ✗ | my_error(ER_EXPLICIT_DECRYPTION_OF_ONLINE_ENCRYPTED_TABLESPACE, MYF(0), | |
| 18190 | space->name); | ||
| 18191 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 18192 | } | ||
| 18193 | } | ||
| 18194 |
3/4✓ Branch 0 taken 131 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
|
145 | DEBUG_SYNC_C("alter_encryption_to_n"); |
| 18195 | // do not want master key decryption to get into way of encryption threads | ||
| 18196 |
2/4✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 145 times.
|
145 | if (!fil_crypt_exclude_tablespace_from_rotation_temporarily(space)) { |
| 18197 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 18198 | } | ||
| 18199 |
3/4✓ Branch 0 taken 131 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
|
145 | DEBUG_SYNC_C("alter_encryption_to_n_tablespace_excluded"); |
| 18200 | /* Unencrypt tablespace */ | ||
| 18201 | 145 | to_encrypt = false; | |
| 18202 | 145 | } else { | |
| 18203 | // If tablespace is encrypted by encryption threads - it cannot be | ||
| 18204 | // re-encrypted with Master Key encryption. It must first decrypted with | ||
| 18205 | // encryption threads. | ||
| 18206 |
3/4✓ Branch 0 taken 26 times.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
|
63 | if (space->crypt_data != nullptr && alter_info->explicit_encryption) { |
| 18207 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | mutex_enter(&crypt_data->mutex); |
| 18208 | 26 | bool is_keyring_encrypted{crypt_data->type != CRYPT_SCHEME_UNENCRYPTED}; | |
| 18209 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | mutex_exit(&crypt_data->mutex); |
| 18210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
|
26 | if (is_keyring_encrypted) { |
| 18211 | ✗ | my_error(ER_ONLINE_KEYRING_TO_MK_RE_ENCRYPTION, MYF(0), space->name); | |
| 18212 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 18213 | } | ||
| 18214 | } | ||
| 18215 | /* Nothing to do */ | ||
| 18216 | 63 | return error; | |
| 18217 | } | ||
| 18218 | |||
| 18219 | /* Get the transaction associated with the current thd */ | ||
| 18220 |
1/2✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
|
305 | trx = check_trx_exists(thd); |
| 18221 |
1/2✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
|
305 | innobase_register_trx(hton, thd, trx); |
| 18222 | |||
| 18223 |
1/2✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
|
305 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 18224 | |||
| 18225 |
4/6✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 299 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
305 | DBUG_EXECUTE_IF("alter_encrypt_tablespace_crash_before_processing", |
| 18226 | DBUG_SUICIDE();); | ||
| 18227 | |||
| 18228 | /* do encryption/unencryption processing now. */ | ||
| 18229 |
1/2✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
|
299 | err = fsp_alter_encrypt_tablespace(thd, space_id, to_encrypt, new_dd_space); |
| 18230 | |||
| 18231 |
4/6✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 212 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
218 | DBUG_EXECUTE_IF("alter_encrypt_tablespace_crash_after_processing", |
| 18232 | DBUG_SUICIDE();); | ||
| 18233 | |||
| 18234 |
1/2✓ Branch 0 taken 212 times.
✗ Branch 1 not taken.
|
212 | error = convert_error_code_to_mysql(err, 0, nullptr); |
| 18235 | 212 | return error; | |
| 18236 | 390 | } | |
| 18237 | |||
| 18238 | /** ALTER an undo tablespace. | ||
| 18239 | @param[in] hton Handlerton of InnoDB | ||
| 18240 | @param[in] thd Connection | ||
| 18241 | @param[in] alter_info How to do the command | ||
| 18242 | @param[in] old_dd_space Tablespace metadata | ||
| 18243 | @param[in] new_dd_space Tablespace metadata | ||
| 18244 | @return MySQL error code*/ | ||
| 18245 | 5595 | static int innodb_alter_tablespace(handlerton *hton, THD *thd, | |
| 18246 | st_alter_tablespace *alter_info, | ||
| 18247 | const dd::Tablespace *old_dd_space, | ||
| 18248 | dd::Tablespace *new_dd_space) { | ||
| 18249 | 5595 | space_id_t space_id = SPACE_UNKNOWN; | |
| 18250 | ulint old_size, new_size; | ||
| 18251 | |||
| 18252 |
1/2✓ Branch 0 taken 5595 times.
✗ Branch 1 not taken.
|
5595 | DBUG_TRACE; |
| 18253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5595 times.
|
5595 | assert(hton == innodb_hton_ptr); |
| 18254 | |||
| 18255 |
2/2✓ Branch 0 taken 5520 times.
✓ Branch 1 taken 75 times.
|
5595 | if (alter_info->ts_alter_tablespace_type != ALTER_TABLESPACE_RENAME && |
| 18256 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 5502 times.
|
5520 | alter_info->ts_alter_tablespace_type != ALTER_TABLESPACE_OPTIONS) { |
| 18257 | 18 | return HA_ADMIN_NOT_IMPLEMENTED; | |
| 18258 | } | ||
| 18259 | |||
| 18260 | /* Name validation should be ensured from the SQL layer. */ | ||
| 18261 |
2/4✓ Branch 0 taken 5577 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5577 times.
|
5577 | ut_ad(0 == validate_tablespace_name(ALTER_TABLESPACE, |
| 18262 | alter_info->tablespace_name)); | ||
| 18263 | |||
| 18264 | /* Be sure that this tablespace is known and valid. */ | ||
| 18265 |
3/6✓ Branch 0 taken 5577 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5576 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
11154 | if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 18266 | 5577 | &space_id) || | |
| 18267 |
8/14✓ Branch 0 taken 5577 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5577 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5577 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5577 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5577 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 5576 times.
✓ Branch 12 taken 5577 times.
✗ Branch 13 not taken.
|
11154 | space_id == SPACE_UNKNOWN || fil_space_get_size(space_id) == 0) { |
| 18268 | 1 | return HA_ERR_TABLESPACE_MISSING; | |
| 18269 | } | ||
| 18270 | |||
| 18271 |
3/4✓ Branch 0 taken 5576 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5575 times.
|
5576 | if (fsp_is_undo_tablespace(space_id)) { |
| 18272 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 18273 | "Cannot ALTER TABLESPACE `%s` because it is an undo " | ||
| 18274 | "tablespace. Please use ALTER UNDO TABLESPACE.", | ||
| 18275 | MYF(0), alter_info->tablespace_name); | ||
| 18276 | |||
| 18277 | 1 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 18278 | } | ||
| 18279 | |||
| 18280 | /* ALTER_TABLESPACE_OPTIONS */ | ||
| 18281 |
2/2✓ Branch 0 taken 5502 times.
✓ Branch 1 taken 73 times.
|
5575 | if (alter_info->ts_alter_tablespace_type == ALTER_TABLESPACE_OPTIONS) { |
| 18282 | 5502 | int err = 0; | |
| 18283 | /* Process the encryption option if specified with the | ||
| 18284 | ALTER TABLESPACE statement. */ | ||
| 18285 |
2/2✓ Branch 0 taken 483 times.
✓ Branch 1 taken 5019 times.
|
5985 | if (alter_info->encryption != nullptr && |
| 18286 |
8/14✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 483 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 483 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 483 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 483 times.
✓ Branch 9 taken 5019 times.
✓ Branch 10 taken 483 times.
✓ Branch 11 taken 5019 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
5985 | new_dd_space->options().exists("encryption")) { |
| 18287 |
1/2✓ Branch 0 taken 390 times.
✗ Branch 1 not taken.
|
483 | err = innobase_alter_encrypt_tablespace(hton, thd, alter_info, |
| 18288 | old_dd_space, new_dd_space); | ||
| 18289 | } | ||
| 18290 | |||
| 18291 | /* Process the AUTOEXTEND_SIZE clause if mentioned with | ||
| 18292 | the ALTER TABLESPACE statement. */ | ||
| 18293 |
4/4✓ Branch 0 taken 5344 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 5018 times.
✓ Branch 3 taken 326 times.
|
10427 | if (!err && alter_info->autoextend_size.has_value() && |
| 18294 |
8/14✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5018 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5018 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5018 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5018 times.
✓ Branch 9 taken 391 times.
✓ Branch 10 taken 5018 times.
✓ Branch 11 taken 391 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
10427 | new_dd_space->options().exists(autoextend_size_str)) { |
| 18295 |
1/2✓ Branch 0 taken 5018 times.
✗ Branch 1 not taken.
|
5018 | err = innobase_alter_autoextend_size_tablespace(hton, alter_info, |
| 18296 | old_dd_space); | ||
| 18297 | } | ||
| 18298 | |||
| 18299 | /* Ignore any other ALTER TABLESPACE options. */ | ||
| 18300 | 5409 | return err; | |
| 18301 | } | ||
| 18302 | |||
| 18303 | /* ALTER_TABLESPACE_RENAME */ | ||
| 18304 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | const char *from = old_dd_space->name().c_str(); |
| 18305 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | const char *to = new_dd_space->name().c_str(); |
| 18306 | |||
| 18307 | /* mysql tablespace can't be renamed */ | ||
| 18308 |
2/4✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 73 times.
|
73 | if (innobase_strcasecmp(from, dict_sys_t::s_dd_space_name) == 0) { |
| 18309 | ✗ | my_printf_error(ER_WRONG_TABLESPACE_NAME, | |
| 18310 | "InnoDB: `mysql` is a reserved" | ||
| 18311 | " tablespace name.", | ||
| 18312 | MYF(0)); | ||
| 18313 | ✗ | return HA_WRONG_CREATE_OPTION; | |
| 18314 | } | ||
| 18315 | |||
| 18316 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | ut_ad(ut_strcmp(from, to) != 0); |
| 18317 | |||
| 18318 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | dberr_t err = fil_rename_tablespace_by_id(space_id, from, to); |
| 18319 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | if (err != DB_SUCCESS) { |
| 18320 | ✗ | return convert_error_code_to_mysql(err, 0, nullptr); | |
| 18321 | } | ||
| 18322 | |||
| 18323 | /* Rename any in-memory cached table->tablespace */ | ||
| 18324 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | dict_sys_mutex_enter(); |
| 18325 |
6/10✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3280 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3353 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3280 times.
✓ Branch 9 taken 73 times.
|
3353 | for (auto table : dict_sys->table_LRU) { |
| 18326 |
6/6✓ Branch 0 taken 3003 times.
✓ Branch 1 taken 277 times.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 2909 times.
✓ Branch 4 taken 94 times.
✓ Branch 5 taken 3186 times.
|
3280 | if (table->tablespace && strcmp(from, table->tablespace) == 0) { |
| 18327 |
1/2✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
|
94 | old_size = mem_heap_get_size(table->heap); |
| 18328 | |||
| 18329 |
1/2✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
|
94 | table->tablespace = mem_heap_strdupl(table->heap, to, strlen(to)); |
| 18330 | |||
| 18331 |
1/2✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
|
94 | new_size = mem_heap_get_size(table->heap); |
| 18332 | 94 | dict_sys->size += new_size - old_size; | |
| 18333 | } | ||
| 18334 | } | ||
| 18335 | |||
| 18336 |
6/10✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1772 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1845 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1772 times.
✓ Branch 9 taken 73 times.
|
1845 | for (auto table : dict_sys->table_non_LRU) { |
| 18337 |
4/6✓ Branch 0 taken 1748 times.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1748 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1772 times.
|
1772 | if (table->tablespace && strcmp(from, table->tablespace) == 0) { |
| 18338 | ✗ | old_size = mem_heap_get_size(table->heap); | |
| 18339 | |||
| 18340 | ✗ | table->tablespace = mem_heap_strdupl(table->heap, to, strlen(to)); | |
| 18341 | |||
| 18342 | ✗ | new_size = mem_heap_get_size(table->heap); | |
| 18343 | ✗ | dict_sys->size += new_size - old_size; | |
| 18344 | } | ||
| 18345 | } | ||
| 18346 | |||
| 18347 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | dict_sys_mutex_exit(); |
| 18348 | |||
| 18349 | 73 | return 0; | |
| 18350 | 5502 | } | |
| 18351 | |||
| 18352 | /** DROP a tablespace. | ||
| 18353 | @param[in] hton Handlerton of InnoDB | ||
| 18354 | @param[in] thd Connection | ||
| 18355 | @param[in] alter_info How to do the command | ||
| 18356 | @param[in] dd_space Tablespace metadata | ||
| 18357 | @return MySQL error code*/ | ||
| 18358 | 888 | static int innodb_drop_tablespace(handlerton *hton, THD *thd, | |
| 18359 | st_alter_tablespace *alter_info, | ||
| 18360 | const dd::Tablespace *dd_space) { | ||
| 18361 | 888 | int error = 0; | |
| 18362 | 888 | space_id_t space_id = SPACE_UNKNOWN; | |
| 18363 | |||
| 18364 |
1/2✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
|
888 | DBUG_TRACE; |
| 18365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 888 times.
|
888 | assert(hton == innodb_hton_ptr); |
| 18366 | |||
| 18367 |
2/4✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 888 times.
✗ Branch 3 not taken.
|
888 | auto dd_space_name = dd_space->name(); |
| 18368 | |||
| 18369 |
2/4✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 888 times.
|
888 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 18370 | |||
| 18371 | /* Name validation should be ensured from the SQL layer. */ | ||
| 18372 |
2/4✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 888 times.
|
888 | ut_ad(0 == |
| 18373 | validate_tablespace_name(DROP_TABLESPACE, alter_info->tablespace_name)); | ||
| 18374 | |||
| 18375 | /* Be sure that this tablespace is known and valid. */ | ||
| 18376 |
2/6✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 888 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
1776 | if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 18377 |
4/8✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 888 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 888 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 888 times.
✗ Branch 7 not taken.
|
2664 | &space_id) || |
| 18378 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 888 times.
|
888 | space_id == SPACE_UNKNOWN) { |
| 18379 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 18380 | } | ||
| 18381 | |||
| 18382 |
3/4✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 887 times.
|
888 | if (fsp_is_undo_tablespace(space_id)) { |
| 18383 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 18384 | "Cannot DROP TABLESPACE `%s` because it is an undo " | ||
| 18385 | "tablespace. Please use DROP UNDO TABLESPACE.", | ||
| 18386 | MYF(0), alter_info->tablespace_name); | ||
| 18387 | |||
| 18388 | 1 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 18389 | } | ||
| 18390 | |||
| 18391 |
3/4✓ Branch 0 taken 887 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 883 times.
|
887 | if (fil_space_get_flags(space_id) == UINT32_UNDEFINED) { |
| 18392 | /* The DD knows about it but the actual tablespace is missing. | ||
| 18393 | Allow it to be dropped from the DD. */ | ||
| 18394 | 4 | return 0; | |
| 18395 | } | ||
| 18396 | |||
| 18397 | /* Get the transaction associated with the current thd. */ | ||
| 18398 |
1/2✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
|
883 | trx_t *trx = check_trx_exists(thd); |
| 18399 |
1/2✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
|
883 | TrxInInnoDB trx_in_innodb(trx); |
| 18400 |
1/2✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
|
883 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 18401 | 883 | ++trx->will_lock; | |
| 18402 | |||
| 18403 | /* Acquire Exclusive MDL on SDI table of tablespace. | ||
| 18404 | This is to prevent concurrent purge on SDI table */ | ||
| 18405 | 883 | MDL_ticket *sdi_mdl = nullptr; | |
| 18406 |
1/2✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
|
883 | dberr_t err = dd_sdi_acquire_exclusive_mdl(thd, space_id, &sdi_mdl); |
| 18407 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 883 times.
|
883 | if (err != DB_SUCCESS) { |
| 18408 | ✗ | error = convert_error_code_to_mysql(err, 0, nullptr); | |
| 18409 | ✗ | return error; | |
| 18410 | } | ||
| 18411 | |||
| 18412 |
2/4✓ Branch 0 taken 883 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 883 times.
✗ Branch 3 not taken.
|
883 | err = log_ddl->write_delete_space_log(trx, nullptr, space_id, |
| 18413 | dd_tablespace_get_filename(dd_space), | ||
| 18414 | true, false); | ||
| 18415 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 883 times.
|
883 | if (err != DB_SUCCESS) { |
| 18416 | ✗ | error = convert_error_code_to_mysql(err, 0, nullptr); | |
| 18417 | } | ||
| 18418 | |||
| 18419 | 883 | return error; | |
| 18420 | 888 | } | |
| 18421 | |||
| 18422 | /** CREATE an undo tablespace. | ||
| 18423 | @param[in] hton Handlerton of InnoDB | ||
| 18424 | @param[in] thd Connection | ||
| 18425 | @param[in] alter_info How to do the command | ||
| 18426 | @param[in,out] dd_space Tablespace metadata | ||
| 18427 | @return MySQL error code*/ | ||
| 18428 | 358 | static int innodb_create_undo_tablespace(handlerton *hton, THD *thd, | |
| 18429 | st_alter_tablespace *alter_info, | ||
| 18430 | dd::Tablespace *dd_space) { | ||
| 18431 | 358 | int error = 0; | |
| 18432 | dberr_t err; | ||
| 18433 | uint32_t flags; | ||
| 18434 | |||
| 18435 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | DBUG_TRACE; |
| 18436 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 358 times.
|
358 | assert(hton == innodb_hton_ptr); |
| 18437 | |||
| 18438 |
2/4✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 358 times.
|
358 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 18439 |
2/4✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 358 times.
|
358 | ut_ad(strcmp(alter_info->data_file_name, |
| 18440 | dd_tablespace_get_filename(dd_space)) == 0); | ||
| 18441 | |||
| 18442 | /* Be sure the input parameters are valid before continuing. */ | ||
| 18443 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | error = validate_create_tablespace_info(IBU, alter_info); |
| 18444 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 343 times.
|
358 | if (error) { |
| 18445 | 15 | return error; | |
| 18446 | } | ||
| 18447 | |||
| 18448 | /* Notify clone about the UNDO DDL and possibly wait. We don't | ||
| 18449 | need similar notification for drop which is recoverable with DDL | ||
| 18450 | log. */ | ||
| 18451 | Clone_notify notifier(Clone_notify::Type::SPACE_UNDO_DDL, | ||
| 18452 |
1/2✓ Branch 0 taken 343 times.
✗ Branch 1 not taken.
|
343 | dict_sys_t::s_invalid_space_id, false); |
| 18453 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 342 times.
|
343 | if (notifier.failed()) { |
| 18454 | 1 | return notifier.get_error(); | |
| 18455 | } | ||
| 18456 | |||
| 18457 | /* Create the tablespace object. */ | ||
| 18458 | |||
| 18459 | /* Serialize all undo tablespace DDLs */ | ||
| 18460 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | mutex_enter(&undo::ddl_mutex); |
| 18461 | |||
| 18462 | /* Get the transaction associated with the current thd and make | ||
| 18463 | sure it will not block this DDL. */ | ||
| 18464 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | check_trx_exists(thd); |
| 18465 | |||
| 18466 | /* Allocate a new transaction for this DDL */ | ||
| 18467 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | trx_t *trx = innobase_trx_allocate(thd); |
| 18468 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 18469 | 342 | ++trx->will_lock; | |
| 18470 | |||
| 18471 | /* Find the next available undo space number and mark it in-use. */ | ||
| 18472 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | space_id_t space_id = undo::get_next_available_space_num(); |
| 18473 |
5/6✓ Branch 0 taken 341 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 341 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 341 times.
|
683 | if (space_id == SPACE_UNKNOWN || |
| 18474 | 341 | undo::spaces->size() == FSP_MAX_UNDO_TABLESPACES) { | |
| 18475 | /* All available explicit undo tablespaces have been used. */ | ||
| 18476 | 1 | ib::error(ER_IB_MSG_MAX_UNDO_SPACES_REACHED, alter_info->tablespace_name, | |
| 18477 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | alter_info->data_file_name, int{FSP_MAX_UNDO_TABLESPACES}); |
| 18478 | 1 | error = HA_ERR_TABLESPACE_EXISTS; | |
| 18479 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | trx_rollback_for_mysql(trx); |
| 18480 | 1 | goto cleanup; | |
| 18481 | } | ||
| 18482 | |||
| 18483 |
1/2✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
|
341 | err = srv_undo_tablespace_create(alter_info->tablespace_name, |
| 18484 | alter_info->data_file_name, space_id); | ||
| 18485 | |||
| 18486 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 339 times.
|
341 | if (err != DB_SUCCESS) { |
| 18487 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | error = convert_error_code_to_mysql(err, 0, nullptr); |
| 18488 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | trx_rollback_for_mysql(trx); |
| 18489 | 2 | goto cleanup; | |
| 18490 | } | ||
| 18491 | |||
| 18492 |
1/2✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
|
339 | innobase_commit_low(trx); |
| 18493 | |||
| 18494 | /* Make sure the DD has the space_id and the flags. */ | ||
| 18495 |
1/2✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
|
339 | flags = fsp_flags_init(univ_page_size, false, false, false, false); |
| 18496 |
1/2✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
|
339 | dd_write_tablespace(dd_space, space_id, flags, DD_SPACE_STATE_ACTIVE); |
| 18497 | |||
| 18498 | /* Mark the undo tablespace 'active' in undo::spaces. */ | ||
| 18499 |
1/2✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
|
339 | undo::set_active(space_id); |
| 18500 |
1/2✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
|
339 | ut_d(ib::info(ER_IB_MSG_UNDO_MARKED_ACTIVE, alter_info->tablespace_name)); |
| 18501 | |||
| 18502 | 342 | cleanup: | |
| 18503 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | trx_free_for_mysql(trx); |
| 18504 | |||
| 18505 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | mutex_exit(&undo::ddl_mutex); |
| 18506 | |||
| 18507 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | ib::info(ER_IB_MSG_CREATED_UNDO_SPACE, alter_info->tablespace_name); |
| 18508 | |||
| 18509 | 342 | return error; | |
| 18510 | 358 | } | |
| 18511 | |||
| 18512 | /** ALTER an undo tablespace to ACTIVE. | ||
| 18513 | @param[in] undo_space Undo Tablespace object | ||
| 18514 | @param[in] dd_state Current state in the DD. | ||
| 18515 | @param[in] dd_space Tablespace metadata | ||
| 18516 | @return MySQL error code*/ | ||
| 18517 | 213 | static int innodb_alter_undo_tablespace_active(undo::Tablespace *undo_space, | |
| 18518 | dd::String_type dd_state, | ||
| 18519 | dd::Tablespace *dd_space) { | ||
| 18520 | /* Change the state of the undo tablespace. | ||
| 18521 | ALTER UNDO TABLESPACE is idempotent. */ | ||
| 18522 |
2/2✓ Branch 0 taken 209 times.
✓ Branch 1 taken 4 times.
|
213 | if (dd_state != dd_space_state_values[DD_SPACE_STATE_ACTIVE]) { |
| 18523 | 209 | dd_tablespace_set_state(dd_space, DD_SPACE_STATE_ACTIVE); | |
| 18524 | } | ||
| 18525 | |||
| 18526 | /* Start using this undo tablespace. */ | ||
| 18527 | 213 | undo_space->alter_active(); | |
| 18528 | |||
| 18529 | 213 | return (0); | |
| 18530 | } | ||
| 18531 | |||
| 18532 | /** ALTER an undo tablespace to INACTIVE. | ||
| 18533 | @param[in] undo_space Undo Tablespace object | ||
| 18534 | @param[in] dd_state Current state in the DD. | ||
| 18535 | @param[in] dd_space Tablespace metadata | ||
| 18536 | @return MySQL error code*/ | ||
| 18537 | 553 | static int innodb_alter_undo_tablespace_inactive(undo::Tablespace *undo_space, | |
| 18538 | dd::String_type dd_state, | ||
| 18539 | dd::Tablespace *dd_space) { | ||
| 18540 | /* If it is already empty, just return. */ | ||
| 18541 |
5/6✓ Branch 0 taken 1 times.
✓ Branch 1 taken 552 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 552 times.
|
554 | if (undo_space->is_empty() && |
| 18542 | 1 | dd_state == dd_space_state_values[DD_SPACE_STATE_EMPTY]) { | |
| 18543 | 1 | return (0); | |
| 18544 | } | ||
| 18545 | |||
| 18546 |
2/2✓ Branch 0 taken 531 times.
✓ Branch 1 taken 21 times.
|
552 | if (undo_space->is_active()) { |
| 18547 | /* There must be at least 2 active undo tablespaces besides the one we | ||
| 18548 | are trying to make inactive explicitly. One of those two could be in | ||
| 18549 | the process of being implicitly truncated. So if one other space is | ||
| 18550 | inactive_implicit, then it is being truncated and will be put back | ||
| 18551 | to active before this undo_space is truncated. */ | ||
| 18552 | 531 | ulint other_active_spaces = 0; | |
| 18553 |
2/2✓ Branch 0 taken 18702 times.
✓ Branch 1 taken 531 times.
|
19233 | for (auto undo_ts : undo::spaces->m_spaces) { |
| 18554 |
2/2✓ Branch 0 taken 18171 times.
✓ Branch 1 taken 531 times.
|
18702 | if (undo_ts != undo_space) { |
| 18555 |
3/4✓ Branch 0 taken 18171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9590 times.
✓ Branch 3 taken 8581 times.
|
18171 | if (undo_ts->is_active()) { |
| 18556 | 9590 | other_active_spaces++; | |
| 18557 |
5/6✓ Branch 0 taken 8581 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 8556 times.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 8556 times.
|
8606 | } else if (undo_ts->is_inactive_implicit() && |
| 18558 | 25 | purge_sys->undo_trunc.get_marked_space_num() == | |
| 18559 |
2/4✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
|
25 | undo_ts->num()) { |
| 18560 | 25 | other_active_spaces++; | |
| 18561 | } | ||
| 18562 | } | ||
| 18563 | } | ||
| 18564 | |||
| 18565 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 517 times.
|
531 | if (other_active_spaces < 2) { |
| 18566 | 14 | my_printf_error(ER_DISALLOWED_OPERATION, | |
| 18567 | "Cannot set %s inactive since there would be" | ||
| 18568 | " less than 2 undo tablespaces left active.", | ||
| 18569 | MYF(0), undo_space->space_name()); | ||
| 18570 | |||
| 18571 | 14 | return (HA_ERR_NOT_ALLOWED_COMMAND); | |
| 18572 | } | ||
| 18573 | } | ||
| 18574 | |||
| 18575 | /* If truncation is happening too often on this undo tablespace there | ||
| 18576 | may be too many old files still in the fil_system with their pages | ||
| 18577 | still in the buffer pool. If this is the case, return an error. */ | ||
| 18578 | 538 | auto count = fil_count_undo_deleted(undo_space->num()); | |
| 18579 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 538 times.
|
538 | if (count > CONCURRENT_UNDO_TRUNCATE_LIMIT) { |
| 18580 | ✗ | my_printf_error(ER_DISALLOWED_OPERATION, | |
| 18581 | "Cannot set %s inactive since there would be more" | ||
| 18582 | " than %zu old versions of this undo tablespace" | ||
| 18583 | " in cache. Please wait for the next checkpoint.", | ||
| 18584 | MYF(0), undo_space->space_name(), | ||
| 18585 | CONCURRENT_UNDO_TRUNCATE_LIMIT); | ||
| 18586 | |||
| 18587 | ✗ | return (HA_ERR_NOT_ALLOWED_COMMAND); | |
| 18588 | } | ||
| 18589 | |||
| 18590 | /* Make sure the DD shows inactive if it is active. */ | ||
| 18591 | 538 | dd_tablespace_set_state(dd_space, DD_SPACE_STATE_INACTIVE); | |
| 18592 | |||
| 18593 | /* Apply this to new transactions. */ | ||
| 18594 | 538 | undo_space->set_inactive_explicit(); | |
| 18595 |
1/2✓ Branch 0 taken 538 times.
✗ Branch 1 not taken.
|
538 | ut_d(ib::info(ER_IB_MSG_UNDO_ALTERED_INACTIVE, undo_space->file_name())); |
| 18596 | |||
| 18597 | 538 | srv_wake_purge_thread_if_not_active(); | |
| 18598 | |||
| 18599 | 538 | return (0); | |
| 18600 | } | ||
| 18601 | |||
| 18602 | /** ALTER an undo tablespace. Either make it ACTIVE or INACTIVE. | ||
| 18603 | @param[in] hton Handlerton of InnoDB | ||
| 18604 | @param[in] alter_info How to do the command | ||
| 18605 | @param[in] dd_space Tablespace metadata | ||
| 18606 | @return MySQL error code*/ | ||
| 18607 | 768 | static int innodb_alter_undo_tablespace(handlerton *hton, | |
| 18608 | st_alter_tablespace *alter_info, | ||
| 18609 | dd::Tablespace *dd_space) { | ||
| 18610 | 768 | space_id_t space_id = SPACE_UNKNOWN; | |
| 18611 | |||
| 18612 |
1/2✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
|
768 | DBUG_TRACE; |
| 18613 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 768 times.
|
768 | assert(hton == innodb_hton_ptr); |
| 18614 | |||
| 18615 |
2/4✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 768 times.
|
768 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 18616 | |||
| 18617 | /* Name validation should be ensured from the SQL layer. */ | ||
| 18618 |
2/4✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 768 times.
|
768 | ut_ad(0 == validate_tablespace_name(ALTER_UNDO_TABLESPACE, |
| 18619 | alter_info->tablespace_name)); | ||
| 18620 | |||
| 18621 | /* Be sure that this tablespace is known and valid. */ | ||
| 18622 |
2/6✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 768 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
1536 | if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 18623 | 768 | &space_id) || | |
| 18624 |
7/14✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 768 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 768 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 768 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 768 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 768 times.
✓ Branch 12 taken 768 times.
✗ Branch 13 not taken.
|
1536 | space_id == SPACE_UNKNOWN || fil_space_get_size(space_id) == 0) { |
| 18625 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 18626 | } | ||
| 18627 | |||
| 18628 |
3/4✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 766 times.
|
768 | if (!fsp_is_undo_tablespace(space_id)) { |
| 18629 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 18630 | "Cannot ALTER UNDO TABLESPACE `%s` because it is a " | ||
| 18631 | "general tablespace. Please use ALTER TABLESPACE.", | ||
| 18632 | MYF(0), alter_info->tablespace_name); | ||
| 18633 | |||
| 18634 | 2 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 18635 | } | ||
| 18636 | |||
| 18637 | /* Get the current state of the undo tablespace from the DD. */ | ||
| 18638 | 766 | dd::String_type dd_state; | |
| 18639 |
1/2✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
|
766 | dd_tablespace_get_state(dd_space, &dd_state, space_id); |
| 18640 | |||
| 18641 | /* Serialize all undo tablespace DDLs */ | ||
| 18642 |
1/2✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
|
766 | mutex_enter(&undo::ddl_mutex); |
| 18643 | |||
| 18644 | /* Get the current undo_space object. */ | ||
| 18645 |
1/2✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
|
766 | undo::spaces->s_lock(); |
| 18646 | 766 | space_id_t space_num = undo::id2num(space_id); | |
| 18647 |
1/2✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
|
766 | undo::Tablespace *undo_space = undo::spaces->find(space_num); |
| 18648 | |||
| 18649 | /* ALTER UNDO TABLESPACE is idempotent. */ | ||
| 18650 | 766 | int err = 0; | |
| 18651 |
2/3✓ Branch 0 taken 213 times.
✓ Branch 1 taken 553 times.
✗ Branch 2 not taken.
|
766 | switch (alter_info->ts_alter_tablespace_type) { |
| 18652 | 213 | case ALTER_UNDO_TABLESPACE_SET_ACTIVE: | |
| 18653 |
2/4✓ Branch 0 taken 213 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 213 times.
✗ Branch 3 not taken.
|
213 | err = innodb_alter_undo_tablespace_active(undo_space, dd_state, dd_space); |
| 18654 | 213 | break; | |
| 18655 | |||
| 18656 | 553 | case ALTER_UNDO_TABLESPACE_SET_INACTIVE: | |
| 18657 | err = | ||
| 18658 |
2/4✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 553 times.
✗ Branch 3 not taken.
|
553 | innodb_alter_undo_tablespace_inactive(undo_space, dd_state, dd_space); |
| 18659 | 553 | break; | |
| 18660 | |||
| 18661 | ✗ | default: | |
| 18662 | ✗ | err = HA_ADMIN_NOT_IMPLEMENTED; | |
| 18663 | } | ||
| 18664 | |||
| 18665 |
1/2✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
|
766 | undo::spaces->s_unlock(); |
| 18666 | |||
| 18667 |
1/2✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
|
766 | mutex_exit(&undo::ddl_mutex); |
| 18668 | |||
| 18669 | 766 | return err; | |
| 18670 | 768 | } | |
| 18671 | |||
| 18672 | /** DROP an undo tablespace. | ||
| 18673 | @param[in] hton Handlerton of InnoDB | ||
| 18674 | @param[in] thd Connection | ||
| 18675 | @param[in] alter_info How to do the command | ||
| 18676 | @param[in] dd_space Tablespace metadata | ||
| 18677 | @return MySQL error code*/ | ||
| 18678 | 330 | static int innodb_drop_undo_tablespace(handlerton *hton, THD *thd, | |
| 18679 | st_alter_tablespace *alter_info, | ||
| 18680 | const dd::Tablespace *dd_space) { | ||
| 18681 | 330 | space_id_t space_id = SPACE_UNKNOWN; | |
| 18682 | |||
| 18683 |
1/2✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
|
330 | DBUG_TRACE; |
| 18684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
|
330 | assert(hton == innodb_hton_ptr); |
| 18685 | |||
| 18686 |
2/4✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 330 times.
|
330 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 18687 | |||
| 18688 | /* Name validation should be ensured from the SQL layer. */ | ||
| 18689 |
2/4✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 330 times.
|
330 | ut_ad(0 == validate_tablespace_name(DROP_UNDO_TABLESPACE, |
| 18690 | alter_info->tablespace_name)); | ||
| 18691 | |||
| 18692 | /* Be sure that this tablespace is known and valid. */ | ||
| 18693 |
2/6✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 330 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
660 | if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 18694 |
4/8✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 330 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 330 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 330 times.
✗ Branch 7 not taken.
|
990 | &space_id) || |
| 18695 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
|
330 | space_id == SPACE_UNKNOWN) { |
| 18696 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 18697 | } | ||
| 18698 | |||
| 18699 |
3/4✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 329 times.
|
330 | if (!fsp_is_undo_tablespace(space_id)) { |
| 18700 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 18701 | "Cannot DROP UNDO TABLESPACE `%s` because it is a " | ||
| 18702 | "general tablespace. Please use DROP TABLESPACE.", | ||
| 18703 | MYF(0), alter_info->tablespace_name); | ||
| 18704 | |||
| 18705 | 1 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 18706 | } | ||
| 18707 | |||
| 18708 | /* Serialize all undo tablespace DDLs */ | ||
| 18709 |
1/2✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
|
329 | mutex_enter(&undo::ddl_mutex); |
| 18710 | |||
| 18711 |
1/2✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
|
329 | undo::spaces->x_lock(); |
| 18712 | 329 | space_id_t space_num = undo::id2num(space_id); | |
| 18713 |
1/2✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
|
329 | undo::Tablespace *undo_space = undo::spaces->find(space_num); |
| 18714 | |||
| 18715 | /* If the undo space is missing, allow the DROP UNDO TABLESPACE to | ||
| 18716 | continue to completion. */ | ||
| 18717 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 327 times.
|
329 | if (undo_space == nullptr) { |
| 18718 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | undo::spaces->x_unlock(); |
| 18719 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | mutex_exit(&undo::ddl_mutex); |
| 18720 | |||
| 18721 | /* Start the transaction associated with the current thd so that MySQL | ||
| 18722 | can continue. */ | ||
| 18723 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | trx_t *trx = check_trx_exists(thd); |
| 18724 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 18725 | 2 | ++trx->will_lock; | |
| 18726 | |||
| 18727 | 2 | return (0); | |
| 18728 | } | ||
| 18729 | |||
| 18730 | /* Verify that the undo tablespace is not one of the first two undo spaces, | ||
| 18731 | has been altered inactive and is now empty. */ | ||
| 18732 |
4/6✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 323 times.
|
654 | if (undo_space->num() <= FSP_IMPLICIT_UNDO_TABLESPACES || |
| 18733 |
3/4✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 323 times.
|
327 | !undo_space->is_empty()) { |
| 18734 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | ib::error err_msg; |
| 18735 |
3/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | err_msg << "Cannot drop undo tablespace '" << undo_space->space_name(); |
| 18736 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (undo_space->num() <= FSP_IMPLICIT_UNDO_TABLESPACES) { |
| 18737 | ✗ | err_msg << "' because it was not created explicitly."; | |
| 18738 |
3/10✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
|
4 | } else if (undo_space->is_active() || undo_space->is_inactive_implicit()) { |
| 18739 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | err_msg << "' because it is active. " |
| 18740 |
3/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
8 | << "Please do: ALTER UNDO TABLESPACE " << undo_space->space_name() |
| 18741 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | << " SET INACTIVE;"; |
| 18742 | } else { | ||
| 18743 | err_msg << "' because it is still being truncated." | ||
| 18744 | ✗ | " Please try again later."; | |
| 18745 | } | ||
| 18746 | |||
| 18747 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | undo::spaces->x_unlock(); |
| 18748 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | mutex_exit(&undo::ddl_mutex); |
| 18749 | |||
| 18750 | 4 | return HA_ERR_TABLESPACE_IS_NOT_EMPTY; | |
| 18751 | 4 | } | |
| 18752 | |||
| 18753 | /* We don't need to invalidate buffer pool pages belonging to this undo | ||
| 18754 | tablespace before dropping it, as they will be set as stale and to be | ||
| 18755 | lazily freed. */ | ||
| 18756 | |||
| 18757 | /* Save the file name before undo_space is dropped. */ | ||
| 18758 |
2/4✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 323 times.
✗ Branch 3 not taken.
|
323 | std::string file_name{undo_space->file_name()}; |
| 18759 | |||
| 18760 | /* Empty and inactive, take it out of view. */ | ||
| 18761 |
1/2✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
|
323 | undo::spaces->drop(undo_space); |
| 18762 |
1/2✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
|
323 | undo::spaces->x_unlock(); |
| 18763 | |||
| 18764 | /* Get the transaction associated with the current thd and write a | ||
| 18765 | delete_space record to the DDL_LOG. */ | ||
| 18766 |
1/2✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
|
323 | trx_t *trx = check_trx_exists(thd); |
| 18767 |
1/2✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
|
323 | TrxInInnoDB trx_in_innodb(trx); |
| 18768 |
1/2✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
|
323 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 18769 | 323 | ++trx->will_lock; | |
| 18770 | |||
| 18771 |
1/2✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
|
323 | auto err = log_ddl->write_delete_space_log(trx, nullptr, space_id, |
| 18772 | file_name.c_str(), true, false); | ||
| 18773 | 323 | int error = 0; | |
| 18774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 323 times.
|
323 | if (err != DB_SUCCESS) { |
| 18775 | ✗ | error = convert_error_code_to_mysql(err, 0, nullptr); | |
| 18776 | } | ||
| 18777 | |||
| 18778 |
1/2✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
|
323 | mutex_exit(&undo::ddl_mutex); |
| 18779 | |||
| 18780 |
1/2✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
|
323 | ib::info(ER_IB_MSG_DROPPED_UNDO_SPACE, alter_info->tablespace_name); |
| 18781 | |||
| 18782 | 323 | return error; | |
| 18783 | 330 | } | |
| 18784 | |||
| 18785 | /** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces. | ||
| 18786 | @param[in] hton Handlerton of InnoDB | ||
| 18787 | @param[in] thd Connection | ||
| 18788 | @param[in] alter_info Describes the command and how to do it. | ||
| 18789 | @param[in] old_ts_def Old version of dd::Tablespace object for the | ||
| 18790 | tablespace. | ||
| 18791 | @param[in,out] new_ts_def New version of dd::Tablespace object for the | ||
| 18792 | tablespace. Can be adjusted by SE. Changes will be persisted in the | ||
| 18793 | data-dictionary at statement commit. | ||
| 18794 | @return MySQL error code*/ | ||
| 18795 | 8896 | static int innobase_alter_tablespace(handlerton *hton, THD *thd, | |
| 18796 | st_alter_tablespace *alter_info, | ||
| 18797 | const dd::Tablespace *old_ts_def, | ||
| 18798 | dd::Tablespace *new_ts_def) { | ||
| 18799 | 8896 | int error = 0; /* return zero for success */ | |
| 18800 |
1/2✓ Branch 0 taken 8896 times.
✗ Branch 1 not taken.
|
8896 | DBUG_TRACE; |
| 18801 | |||
| 18802 |
4/4✓ Branch 0 taken 8895 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8894 times.
|
8896 | if (srv_read_only_mode || srv_force_recovery > 0) { |
| 18803 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | my_printf_error(ER_INNODB_READ_ONLY, |
| 18804 | "Changes to undo tablespaces are not allowed in" | ||
| 18805 | " %s mode", | ||
| 18806 | MYF(0), | ||
| 18807 | (srv_read_only_mode ? "read_only" : "force_recovery")); | ||
| 18808 | 2 | error = HA_ERR_INNODB_READ_ONLY; | |
| 18809 | 2 | goto handle_error; | |
| 18810 | } | ||
| 18811 | |||
| 18812 |
7/7✓ Branch 0 taken 952 times.
✓ Branch 1 taken 5595 times.
✓ Branch 2 taken 888 times.
✓ Branch 3 taken 358 times.
✓ Branch 4 taken 768 times.
✓ Branch 5 taken 330 times.
✓ Branch 6 taken 3 times.
|
8894 | switch (alter_info->ts_cmd_type) { |
| 18813 | 952 | case CREATE_TABLESPACE: | |
| 18814 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 952 times.
|
952 | ut_ad(new_ts_def != nullptr); |
| 18815 |
1/2✓ Branch 0 taken 950 times.
✗ Branch 1 not taken.
|
952 | error = innodb_create_tablespace(hton, thd, alter_info, new_ts_def); |
| 18816 | 950 | break; | |
| 18817 | |||
| 18818 | 5595 | case ALTER_TABLESPACE: | |
| 18819 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5595 times.
|
5595 | ut_ad(old_ts_def != nullptr); |
| 18820 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5595 times.
|
5595 | ut_ad(new_ts_def != nullptr); |
| 18821 |
1/2✓ Branch 0 taken 5502 times.
✗ Branch 1 not taken.
|
5595 | error = innodb_alter_tablespace(hton, thd, alter_info, old_ts_def, |
| 18822 | new_ts_def); | ||
| 18823 | 5502 | break; | |
| 18824 | |||
| 18825 | 888 | case DROP_TABLESPACE: | |
| 18826 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 888 times.
|
888 | ut_ad(old_ts_def != nullptr); |
| 18827 |
1/2✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
|
888 | error = innodb_drop_tablespace(hton, thd, alter_info, old_ts_def); |
| 18828 | 888 | break; | |
| 18829 | |||
| 18830 | 358 | case CREATE_UNDO_TABLESPACE: | |
| 18831 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | error = innodb_create_undo_tablespace(hton, thd, alter_info, new_ts_def); |
| 18832 | 358 | break; | |
| 18833 | |||
| 18834 | 768 | case ALTER_UNDO_TABLESPACE: | |
| 18835 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 768 times.
|
768 | ut_ad(new_ts_def != nullptr); |
| 18836 |
1/2✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
|
768 | error = innodb_alter_undo_tablespace(hton, alter_info, new_ts_def); |
| 18837 | 768 | break; | |
| 18838 | |||
| 18839 | 330 | case DROP_UNDO_TABLESPACE: | |
| 18840 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
|
330 | ut_ad(old_ts_def != nullptr); |
| 18841 |
1/2✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
|
330 | error = innodb_drop_undo_tablespace(hton, thd, alter_info, old_ts_def); |
| 18842 | 330 | break; | |
| 18843 | |||
| 18844 | 3 | default: | |
| 18845 | 3 | error = HA_ADMIN_NOT_IMPLEMENTED; | |
| 18846 | } | ||
| 18847 | |||
| 18848 | 8801 | handle_error: | |
| 18849 |
2/2✓ Branch 0 taken 201 times.
✓ Branch 1 taken 8600 times.
|
8801 | if (error) { |
| 18850 | /* These are the most common message params */ | ||
| 18851 | 201 | const char *ibd_type = "TABLESPACE"; | |
| 18852 | 201 | const char *undo_type = "UNDO TABLESPACE"; | |
| 18853 | 201 | uint32_t code = ER_CREATE_FILEGROUP_FAILED; | |
| 18854 | 201 | const char *subject = ibd_type; | |
| 18855 | |||
| 18856 | /* Modify those params as needed. */ | ||
| 18857 |
7/11✓ Branch 0 taken 68 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
201 | switch (alter_info->ts_cmd_type) { |
| 18858 | 68 | case CREATE_TABLESPACE: | |
| 18859 | 68 | break; | |
| 18860 | 87 | case ALTER_TABLESPACE: | |
| 18861 | 87 | code = ER_ALTER_FILEGROUP_FAILED; | |
| 18862 | 87 | break; | |
| 18863 | 2 | case DROP_TABLESPACE: | |
| 18864 | 2 | code = ER_DROP_FILEGROUP_FAILED; | |
| 18865 | 2 | break; | |
| 18866 | 20 | case CREATE_UNDO_TABLESPACE: | |
| 18867 | 20 | subject = undo_type; | |
| 18868 | 20 | break; | |
| 18869 | 16 | case ALTER_UNDO_TABLESPACE: | |
| 18870 | 16 | code = ER_ALTER_FILEGROUP_FAILED; | |
| 18871 | 16 | subject = undo_type; | |
| 18872 | 16 | break; | |
| 18873 | 5 | case DROP_UNDO_TABLESPACE: | |
| 18874 | 5 | code = ER_DROP_FILEGROUP_FAILED; | |
| 18875 | 5 | subject = undo_type; | |
| 18876 | 5 | break; | |
| 18877 | 3 | case CREATE_LOGFILE_GROUP: | |
| 18878 | case DROP_LOGFILE_GROUP: | ||
| 18879 | case ALTER_LOGFILE_GROUP: | ||
| 18880 | 3 | subject = "LOGFILE GROUP"; | |
| 18881 | 3 | break; | |
| 18882 | ✗ | case ALTER_ACCESS_MODE_TABLESPACE: | |
| 18883 | ✗ | subject = "ACCESS MODE"; | |
| 18884 | ✗ | break; | |
| 18885 | ✗ | case CHANGE_FILE_TABLESPACE: | |
| 18886 | ✗ | subject = "CHANGE FILE"; | |
| 18887 | ✗ | break; | |
| 18888 | ✗ | case TS_CMD_NOT_DEFINED: | |
| 18889 | ✗ | subject = "UNKNOWN"; | |
| 18890 | ✗ | break; | |
| 18891 | } | ||
| 18892 | |||
| 18893 |
2/3✓ Branch 0 taken 198 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
201 | switch (alter_info->ts_cmd_type) { |
| 18894 | 198 | case CREATE_TABLESPACE: | |
| 18895 | case ALTER_TABLESPACE: | ||
| 18896 | case DROP_TABLESPACE: | ||
| 18897 | case CREATE_UNDO_TABLESPACE: | ||
| 18898 | case ALTER_UNDO_TABLESPACE: | ||
| 18899 | case DROP_UNDO_TABLESPACE: | ||
| 18900 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | ib_errf(thd, IB_LOG_LEVEL_ERROR, code, "%s %s", subject, |
| 18901 | alter_info->tablespace_name); | ||
| 18902 | 198 | break; | |
| 18903 | |||
| 18904 | 3 | case CREATE_LOGFILE_GROUP: | |
| 18905 | case ALTER_ACCESS_MODE_TABLESPACE: | ||
| 18906 | case DROP_LOGFILE_GROUP: | ||
| 18907 | case ALTER_LOGFILE_GROUP: | ||
| 18908 | case CHANGE_FILE_TABLESPACE: | ||
| 18909 | case TS_CMD_NOT_DEFINED: | ||
| 18910 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | my_error(ER_FEATURE_UNSUPPORTED, MYF(0), subject, "by InnoDB"); |
| 18911 | 3 | break; | |
| 18912 | } | ||
| 18913 | } | ||
| 18914 | |||
| 18915 | 8801 | return error; | |
| 18916 | 8801 | } | |
| 18917 | |||
| 18918 | /** Renames an InnoDB table. | ||
| 18919 | @param[in] from Old name of the table. | ||
| 18920 | @param[in] to New name of the table. | ||
| 18921 | @param[in] from_table_def dd::Table object describing old version | ||
| 18922 | of table. | ||
| 18923 | @param[in,out] to_table_def dd::Table object describing version of | ||
| 18924 | table with new name. Can be updated by SE. Changes are persisted to the | ||
| 18925 | dictionary at statement commit time. | ||
| 18926 | @return 0 or error code */ | ||
| 18927 | 16687 | int ha_innobase::rename_table(const char *from, const char *to, | |
| 18928 | const dd::Table *from_table_def, | ||
| 18929 | dd::Table *to_table_def) { | ||
| 18930 |
1/2✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
|
16687 | THD *thd = ha_thd(); |
| 18931 |
1/2✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
|
16687 | trx_t *trx = check_trx_exists(thd); |
| 18932 |
1/2✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
|
16687 | TrxInInnoDB trx_in_innodb(trx); |
| 18933 | |||
| 18934 |
1/2✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
|
16687 | DBUG_TRACE; |
| 18935 |
3/6✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16687 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16687 times.
|
16687 | ut_ad(from_table_def->se_private_id() == to_table_def->se_private_id()); |
| 18936 |
5/10✓ Branch 0 taken 16687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16687 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16687 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16687 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 16687 times.
|
16687 | ut_ad(from_table_def->se_private_data().raw_string() == |
| 18937 | to_table_def->se_private_data().raw_string()); | ||
| 18938 | |||
| 18939 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16684 times.
|
16687 | if (high_level_read_only) { |
| 18940 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 18941 | 3 | return HA_ERR_TABLE_READONLY; | |
| 18942 | } | ||
| 18943 | |||
| 18944 |
4/6✓ Branch 0 taken 16684 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16684 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 16681 times.
|
16684 | if (dict_sys_t::is_dd_table_id(to_table_def->se_private_id())) { |
| 18945 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | my_error(ER_NOT_ALLOWED_COMMAND, MYF(0)); |
| 18946 | 3 | return HA_ERR_UNSUPPORTED; | |
| 18947 | } | ||
| 18948 | |||
| 18949 |
1/2✓ Branch 0 taken 16681 times.
✗ Branch 1 not taken.
|
16681 | innobase_register_trx(ht, thd, trx); |
| 18950 | |||
| 18951 |
1/2✓ Branch 0 taken 16636 times.
✗ Branch 1 not taken.
|
16681 | return innobase_basic_ddl::rename_impl<dd::Table>( |
| 18952 | 16636 | thd, from, to, from_table_def, to_table_def, nullptr); | |
| 18953 | 16642 | } | |
| 18954 | |||
| 18955 | /** Returns the exact number of records that this client can see using this | ||
| 18956 | handler object. | ||
| 18957 | @return Error code in case something goes wrong. | ||
| 18958 | These errors will abort the current query: | ||
| 18959 | case HA_ERR_LOCK_DEADLOCK: | ||
| 18960 | case HA_ERR_LOCK_TABLE_FULL: | ||
| 18961 | case HA_ERR_LOCK_WAIT_TIMEOUT: | ||
| 18962 | case HA_ERR_QUERY_INTERRUPTED: | ||
| 18963 | For other error codes, the server will fall back to counting records. */ | ||
| 18964 | |||
| 18965 | 32101 | int ha_innobase::records(ha_rows *num_rows) /*!< out: number of rows */ | |
| 18966 | { | ||
| 18967 |
1/2✓ Branch 0 taken 32101 times.
✗ Branch 1 not taken.
|
32101 | DBUG_TRACE; |
| 18968 | |||
| 18969 | dberr_t ret; | ||
| 18970 | 32101 | ulint n_rows = 0; /* Record count in this view */ | |
| 18971 | |||
| 18972 |
1/2✓ Branch 0 taken 32101 times.
✗ Branch 1 not taken.
|
32101 | update_thd(); |
| 18973 | |||
| 18974 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 32065 times.
|
32101 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 18975 | 36 | ib_senderrf(m_user_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, | |
| 18976 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | table->s->table_name.str); |
| 18977 | |||
| 18978 | 36 | *num_rows = HA_POS_ERROR; | |
| 18979 | 36 | return HA_ERR_NO_SUCH_TABLE; | |
| 18980 | |||
| 18981 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32065 times.
|
32065 | } else if (m_prebuilt->table->ibd_file_missing) { |
| 18982 | ✗ | ib_senderrf(m_user_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING, | |
| 18983 | ✗ | table->s->table_name.str); | |
| 18984 | |||
| 18985 | ✗ | *num_rows = HA_POS_ERROR; | |
| 18986 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 18987 | |||
| 18988 |
2/4✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32065 times.
|
32065 | } else if (m_prebuilt->table->is_corrupted()) { |
| 18989 | ✗ | ib_errf(m_user_thd, IB_LOG_LEVEL_WARN, ER_INNODB_INDEX_CORRUPT, | |
| 18990 | ✗ | "Table '%s' is corrupt.", table->s->table_name.str); | |
| 18991 | |||
| 18992 | ✗ | *num_rows = HA_POS_ERROR; | |
| 18993 | ✗ | return HA_ERR_INDEX_CORRUPT; | |
| 18994 | } | ||
| 18995 | |||
| 18996 |
1/2✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
|
32065 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 18997 | |||
| 18998 | 32065 | m_prebuilt->trx->op_info = "counting records"; | |
| 18999 | |||
| 19000 |
1/2✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
|
32065 | dict_index_t *index = m_prebuilt->table->first_index(); |
| 19001 | |||
| 19002 |
2/4✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32065 times.
|
32065 | ut_ad(index->is_clustered()); |
| 19003 | |||
| 19004 |
1/2✓ Branch 0 taken 32065 times.
✗ Branch 1 not taken.
|
32065 | m_prebuilt->index_usable = index->is_usable(m_prebuilt->trx); |
| 19005 | |||
| 19006 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 32064 times.
|
32065 | if (!m_prebuilt->index_usable) { |
| 19007 | 1 | *num_rows = HA_POS_ERROR; | |
| 19008 | 1 | return HA_ERR_TABLE_DEF_CHANGED; | |
| 19009 | } | ||
| 19010 | |||
| 19011 | /* (Re)Build the m_prebuilt->mysql_template if it is null to use | ||
| 19012 | the clustered index and just the key, no off-record data. */ | ||
| 19013 | 32064 | m_prebuilt->index = index; | |
| 19014 |
1/2✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
|
32064 | m_prebuilt->clear_search_tuples(); |
| 19015 | 32064 | m_prebuilt->read_just_key = 1; | |
| 19016 |
1/2✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
|
32064 | build_template(false); |
| 19017 | |||
| 19018 |
1/2✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
|
32064 | size_t max_threads = thd_parallel_read_threads(m_prebuilt->trx->mysql_thd); |
| 19019 | |||
| 19020 | /* Count the records in the clustered index */ | ||
| 19021 | ret = | ||
| 19022 |
1/2✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
|
32064 | row_scan_index_for_mysql(m_prebuilt, index, max_threads, false, &n_rows); |
| 19023 |
1/2✓ Branch 0 taken 32064 times.
✗ Branch 1 not taken.
|
32064 | reset_template(); |
| 19024 |
3/4✓ Branch 0 taken 32032 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
32064 | switch (ret) { |
| 19025 | 32032 | case DB_SUCCESS: | |
| 19026 | 32032 | break; | |
| 19027 | 30 | case DB_DEADLOCK: | |
| 19028 | case DB_LOCK_TABLE_FULL: | ||
| 19029 | case DB_LOCK_WAIT_TIMEOUT: | ||
| 19030 | 30 | *num_rows = HA_POS_ERROR; | |
| 19031 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | return convert_error_code_to_mysql(ret, 0, m_user_thd); |
| 19032 | 2 | case DB_INTERRUPTED: | |
| 19033 | 2 | *num_rows = HA_POS_ERROR; | |
| 19034 | 2 | return HA_ERR_QUERY_INTERRUPTED; | |
| 19035 | ✗ | default: | |
| 19036 | /* No other error besides the three below is returned from | ||
| 19037 | row_scan_index_for_mysql(). Make a debug catch. */ | ||
| 19038 | ✗ | *num_rows = HA_POS_ERROR; | |
| 19039 | ✗ | return -1; | |
| 19040 | } | ||
| 19041 | |||
| 19042 | 32032 | m_prebuilt->trx->op_info = ""; | |
| 19043 | |||
| 19044 |
2/4✓ Branch 0 taken 32032 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32032 times.
|
32032 | if (thd_killed(m_user_thd)) { |
| 19045 | ✗ | *num_rows = HA_POS_ERROR; | |
| 19046 | ✗ | return HA_ERR_QUERY_INTERRUPTED; | |
| 19047 | } | ||
| 19048 | |||
| 19049 | 32032 | *num_rows = n_rows; | |
| 19050 | 32032 | return 0; | |
| 19051 | 32101 | } | |
| 19052 | |||
| 19053 | /** Estimates the number of index records in a range. | ||
| 19054 | @return estimated number of rows */ | ||
| 19055 | |||
| 19056 | 497841 | ha_rows ha_innobase::records_in_range( | |
| 19057 | uint keynr, /*!< in: index number */ | ||
| 19058 | key_range *min_key, /*!< in: start key value of the | ||
| 19059 | range, may also be 0 */ | ||
| 19060 | key_range *max_key) /*!< in: range end key val, may | ||
| 19061 | also be 0 */ | ||
| 19062 | { | ||
| 19063 | KEY *key; | ||
| 19064 | dict_index_t *index; | ||
| 19065 | dtuple_t *range_start; | ||
| 19066 | dtuple_t *range_end; | ||
| 19067 | int64_t n_rows; | ||
| 19068 | page_cur_mode_t mode1; | ||
| 19069 | page_cur_mode_t mode2; | ||
| 19070 | mem_heap_t *heap; | ||
| 19071 | |||
| 19072 |
1/2✓ Branch 0 taken 497844 times.
✗ Branch 1 not taken.
|
497841 | DBUG_TRACE; |
| 19073 | |||
| 19074 |
3/6✓ Branch 0 taken 497844 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 497844 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 497844 times.
|
497844 | ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 19075 | |||
| 19076 | 497844 | m_prebuilt->trx->op_info = "estimating records in index range"; | |
| 19077 | |||
| 19078 |
1/2✓ Branch 0 taken 497843 times.
✗ Branch 1 not taken.
|
497844 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 19079 | |||
| 19080 | 497843 | active_index = keynr; | |
| 19081 | |||
| 19082 | 497843 | key = table->key_info + active_index; | |
| 19083 | |||
| 19084 |
1/2✓ Branch 0 taken 497844 times.
✗ Branch 1 not taken.
|
497843 | index = innobase_get_index(keynr); |
| 19085 | |||
| 19086 | /* There exists possibility of not being able to find requested | ||
| 19087 | index due to inconsistency between MySQL and InoDB dictionary info. | ||
| 19088 | Necessary message should have been printed in innobase_get_index() */ | ||
| 19089 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 497843 times.
|
497844 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 19090 | ✗ | n_rows = HA_POS_ERROR; | |
| 19091 | ✗ | goto func_exit; | |
| 19092 | } | ||
| 19093 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 497843 times.
|
497843 | if (!index) { |
| 19094 | ✗ | n_rows = HA_POS_ERROR; | |
| 19095 | ✗ | goto func_exit; | |
| 19096 | } | ||
| 19097 |
3/4✓ Branch 0 taken 497844 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 497836 times.
|
497843 | if (index->is_corrupted()) { |
| 19098 | 8 | n_rows = HA_ERR_INDEX_CORRUPT; | |
| 19099 | 8 | goto func_exit; | |
| 19100 | } | ||
| 19101 |
3/4✓ Branch 0 taken 497836 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 497834 times.
|
497836 | if (!index->is_usable(m_prebuilt->trx)) { |
| 19102 | 2 | n_rows = HA_ERR_TABLE_DEF_CHANGED; | |
| 19103 | 2 | goto func_exit; | |
| 19104 | } | ||
| 19105 | |||
| 19106 | 995667 | heap = mem_heap_create( | |
| 19107 |
1/2✓ Branch 0 taken 497833 times.
✗ Branch 1 not taken.
|
497834 | 2 * (key->actual_key_parts * sizeof(dfield_t) + sizeof(dtuple_t)), |
| 19108 | UT_LOCATION_HERE); | ||
| 19109 | |||
| 19110 |
1/2✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
|
497833 | range_start = dtuple_create(heap, key->actual_key_parts); |
| 19111 |
1/2✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
|
497834 | dict_index_copy_types(range_start, index, key->actual_key_parts); |
| 19112 | |||
| 19113 |
1/2✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
|
497834 | range_end = dtuple_create(heap, key->actual_key_parts); |
| 19114 |
1/2✓ Branch 0 taken 497833 times.
✗ Branch 1 not taken.
|
497834 | dict_index_copy_types(range_end, index, key->actual_key_parts); |
| 19115 | |||
| 19116 |
4/4✓ Branch 0 taken 490119 times.
✓ Branch 1 taken 7714 times.
✓ Branch 2 taken 490119 times.
✓ Branch 3 taken 7714 times.
|
987952 | row_sel_convert_mysql_key_to_innobase( |
| 19117 |
1/2✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
|
497833 | range_start, m_prebuilt->srch_key_val1, m_prebuilt->srch_key_val_len, |
| 19118 | index, (byte *)(min_key ? min_key->key : (const uchar *)nullptr), | ||
| 19119 | 490119 | (ulint)(min_key ? min_key->length : 0)); | |
| 19120 | |||
| 19121 |
3/4✓ Branch 0 taken 490120 times.
✓ Branch 1 taken 7714 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 497834 times.
|
497834 | assert(min_key ? range_start->n_fields > 0 : range_start->n_fields == 0); |
| 19122 | |||
| 19123 |
4/4✓ Branch 0 taken 415589 times.
✓ Branch 1 taken 82245 times.
✓ Branch 2 taken 415589 times.
✓ Branch 3 taken 82245 times.
|
913423 | row_sel_convert_mysql_key_to_innobase( |
| 19124 |
1/2✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
|
497834 | range_end, m_prebuilt->srch_key_val2, m_prebuilt->srch_key_val_len, index, |
| 19125 | (byte *)(max_key ? max_key->key : (const uchar *)nullptr), | ||
| 19126 | 415589 | (ulint)(max_key ? max_key->length : 0)); | |
| 19127 | |||
| 19128 |
3/4✓ Branch 0 taken 415589 times.
✓ Branch 1 taken 82245 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 497834 times.
|
497834 | assert(max_key ? range_end->n_fields > 0 : range_end->n_fields == 0); |
| 19129 | |||
| 19130 |
3/4✓ Branch 0 taken 490120 times.
✓ Branch 1 taken 7714 times.
✓ Branch 2 taken 497832 times.
✗ Branch 3 not taken.
|
497834 | mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag |
| 19131 | : HA_READ_KEY_EXACT); | ||
| 19132 | |||
| 19133 |
3/4✓ Branch 0 taken 415586 times.
✓ Branch 1 taken 82246 times.
✓ Branch 2 taken 497832 times.
✗ Branch 3 not taken.
|
497832 | mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag |
| 19134 | : HA_READ_KEY_EXACT); | ||
| 19135 | |||
| 19136 |
2/4✓ Branch 0 taken 497832 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 497832 times.
✗ Branch 3 not taken.
|
497832 | if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) { |
| 19137 |
3/4✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 568 times.
✓ Branch 3 taken 497266 times.
|
497832 | if (dict_index_is_spatial(index)) { |
| 19138 | /*Only min_key used in spatial index. */ | ||
| 19139 |
1/2✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
|
568 | n_rows = rtr_estimate_n_rows_in_range(index, range_start, mode1); |
| 19140 | } else { | ||
| 19141 |
1/2✓ Branch 0 taken 497266 times.
✗ Branch 1 not taken.
|
497266 | n_rows = btr_estimate_n_rows_in_range(index, range_start, mode1, |
| 19142 | range_end, mode2); | ||
| 19143 | } | ||
| 19144 | } else { | ||
| 19145 | ✗ | n_rows = HA_POS_ERROR; | |
| 19146 | } | ||
| 19147 | |||
| 19148 |
1/2✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
|
497834 | mem_heap_free(heap); |
| 19149 | |||
| 19150 |
5/8✓ Branch 0 taken 497834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 497686 times.
✓ Branch 3 taken 148 times.
✓ Branch 4 taken 148 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 148 times.
✗ Branch 7 not taken.
|
497834 | DBUG_EXECUTE_IF( |
| 19151 | "print_btr_estimate_n_rows_in_range_return_value", | ||
| 19152 | push_warning_printf(ha_thd(), Sql_condition::SL_WARNING, ER_NO_DEFAULT, | ||
| 19153 | "btr_estimate_n_rows_in_range(): %" PRId64, n_rows);); | ||
| 19154 | |||
| 19155 | 497686 | func_exit: | |
| 19156 | |||
| 19157 | 497844 | m_prebuilt->trx->op_info = (char *)""; | |
| 19158 | |||
| 19159 | /* The MySQL optimizer seems to believe an estimate of 0 rows is | ||
| 19160 | always accurate and may return the result 'Empty set' based on that. | ||
| 19161 | The accuracy is not guaranteed, and even if it were, for a locking | ||
| 19162 | read we should anyway perform the search to set the next-key lock. | ||
| 19163 | Add 1 to the value to make sure MySQL does not make the assumption! */ | ||
| 19164 | |||
| 19165 |
2/2✓ Branch 0 taken 206090 times.
✓ Branch 1 taken 291754 times.
|
497844 | if (n_rows == 0) { |
| 19166 | 206090 | n_rows = 1; | |
| 19167 | } | ||
| 19168 | |||
| 19169 | 497844 | return (ha_rows)n_rows; | |
| 19170 | 497844 | } | |
| 19171 | |||
| 19172 | /** Gives an UPPER BOUND to the number of rows in a table. This is used in | ||
| 19173 | filesort.cc. | ||
| 19174 | @return upper bound of rows */ | ||
| 19175 | |||
| 19176 | 124086 | ha_rows ha_innobase::estimate_rows_upper_bound() { | |
| 19177 | const dict_index_t *index; | ||
| 19178 | ulonglong estimate; | ||
| 19179 | ulonglong local_data_file_length; | ||
| 19180 | |||
| 19181 |
1/2✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
|
124086 | DBUG_TRACE; |
| 19182 | |||
| 19183 | /* We do not know if MySQL can call this function before calling | ||
| 19184 | external_lock(). To be safe, update the thd of the current table | ||
| 19185 | handle. */ | ||
| 19186 | |||
| 19187 |
2/4✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 124087 times.
✗ Branch 3 not taken.
|
124087 | update_thd(ha_thd()); |
| 19188 | |||
| 19189 |
1/2✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
|
124087 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 19190 | |||
| 19191 | 124087 | m_prebuilt->trx->op_info = "calculating upper bound for table rows"; | |
| 19192 | |||
| 19193 |
1/2✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
|
124087 | index = m_prebuilt->table->first_index(); |
| 19194 | |||
| 19195 | 124087 | ulint stat_n_leaf_pages = index->stat_n_leaf_pages; | |
| 19196 | |||
| 19197 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 124087 times.
|
124087 | ut_a(stat_n_leaf_pages > 0); |
| 19198 | |||
| 19199 | 124087 | local_data_file_length = ((ulonglong)stat_n_leaf_pages) * UNIV_PAGE_SIZE; | |
| 19200 | |||
| 19201 | /* Calculate a minimum length for a clustered index record and from | ||
| 19202 | that an upper bound for the number of rows. Since we only calculate | ||
| 19203 | new statistics in row0mysql.cc when a table has grown by a threshold | ||
| 19204 | factor, we must add a safety factor 2 in front of the formula below. */ | ||
| 19205 | |||
| 19206 |
1/2✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
|
124087 | estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index); |
| 19207 | |||
| 19208 | 124087 | m_prebuilt->trx->op_info = ""; | |
| 19209 | |||
| 19210 | /* Set num_rows less than MERGEBUFF to simulate the case where we do | ||
| 19211 | not have enough space to merge the externally sorted file blocks. */ | ||
| 19212 |
2/6✓ Branch 0 taken 124087 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 124087 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
124087 | DBUG_EXECUTE_IF("set_num_rows_lt_MERGEBUFF", estimate = 2; |
| 19213 | DBUG_SET("-d,set_num_rows_lt_MERGEBUFF");); | ||
| 19214 | |||
| 19215 | 124087 | return (ha_rows)estimate; | |
| 19216 | 124087 | } | |
| 19217 | |||
| 19218 | /** How many seeks it will take to read through the table. This is to be | ||
| 19219 | comparable to the number returned by records_in_range so that we can | ||
| 19220 | decide if we should scan the table or use keys. | ||
| 19221 | @return estimated time measured in disk seeks */ | ||
| 19222 | |||
| 19223 | 42858758 | double ha_innobase::scan_time() { | |
| 19224 | /* Since MySQL seems to favor table scans too much over index | ||
| 19225 | searches, we pretend that a sequential read takes the same time | ||
| 19226 | as a random disk read, that is, we do not divide the following | ||
| 19227 | by 10, which would be physically realistic. */ | ||
| 19228 | |||
| 19229 | /* The locking below is disabled for performance reasons. Without | ||
| 19230 | it we could end up returning uninitialized value to the caller, | ||
| 19231 | which in the worst case could make some query plan go bogus or | ||
| 19232 | issue a Valgrind warning. */ | ||
| 19233 | |||
| 19234 |
2/2✓ Branch 0 taken 1759 times.
✓ Branch 1 taken 42856999 times.
|
42858758 | if (m_prebuilt == nullptr) { |
| 19235 | /* In case of derived table, Optimizer will try to fetch stat | ||
| 19236 | for table even before table is create or open. In such | ||
| 19237 | cases return default value of 1. | ||
| 19238 | TODO: This will be further improved to return some approximate | ||
| 19239 | estimate but that would also needs pre-population of stats | ||
| 19240 | structure. As of now approach is in sync with MyISAM. */ | ||
| 19241 | 1759 | return (ulonglong2double(stats.data_file_length) / IO_SIZE + 2); | |
| 19242 | } | ||
| 19243 | |||
| 19244 | ulint stat_clustered_index_size; | ||
| 19245 | |||
| 19246 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42857193 times.
|
42856999 | ut_a(m_prebuilt->table->stat_initialized); |
| 19247 | |||
| 19248 | 42857193 | stat_clustered_index_size = m_prebuilt->table->stat_clustered_index_size; | |
| 19249 | |||
| 19250 | 42857193 | return ((double)stat_clustered_index_size); | |
| 19251 | } | ||
| 19252 | |||
| 19253 | /** Calculate the time it takes to read a set of ranges through an index | ||
| 19254 | This enables us to optimise reads for clustered indexes. | ||
| 19255 | @return estimated time measured in disk seeks */ | ||
| 19256 | |||
| 19257 | 748655 | double ha_innobase::read_time( | |
| 19258 | uint index, /*!< in: key number */ | ||
| 19259 | uint ranges, /*!< in: how many ranges */ | ||
| 19260 | ha_rows rows) /*!< in: estimated number of rows in the ranges */ | ||
| 19261 | { | ||
| 19262 | ha_rows total_rows; | ||
| 19263 | |||
| 19264 |
2/2✓ Branch 0 taken 357579 times.
✓ Branch 1 taken 391076 times.
|
748655 | if (index != table->s->primary_key) { |
| 19265 | /* Not clustered */ | ||
| 19266 | 357579 | return (handler::read_time(index, ranges, rows)); | |
| 19267 | } | ||
| 19268 | |||
| 19269 |
2/2✓ Branch 0 taken 265822 times.
✓ Branch 1 taken 125254 times.
|
391076 | if (rows <= 2) { |
| 19270 | 265822 | return ((double)rows); | |
| 19271 | } | ||
| 19272 | |||
| 19273 | /* Assume that the read time is proportional to the scan time for all | ||
| 19274 | rows + at most one seek per range. */ | ||
| 19275 | |||
| 19276 | 125254 | double time_for_scan = scan_time(); | |
| 19277 | |||
| 19278 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 125286 times.
|
125286 | if ((total_rows = estimate_rows_upper_bound()) < rows) { |
| 19279 | 1 | return (time_for_scan); | |
| 19280 | } | ||
| 19281 | |||
| 19282 | 125286 | return (ranges + (double)rows / (double)total_rows * time_for_scan); | |
| 19283 | } | ||
| 19284 | |||
| 19285 | /** Return the size of the InnoDB memory buffer. */ | ||
| 19286 | |||
| 19287 | 2703169 | longlong ha_innobase::get_memory_buffer_size() const { | |
| 19288 | 2703169 | return (srv_buf_pool_curr_size); | |
| 19289 | } | ||
| 19290 | |||
| 19291 | /** Update the system variable with the given value of the InnoDB | ||
| 19292 | buffer pool size. | ||
| 19293 | @param[in] buf_pool_size given value of buffer pool size.*/ | ||
| 19294 | 23 | void innodb_set_buf_pool_size(long long buf_pool_size) { | |
| 19295 | 23 | srv_buf_pool_curr_size = buf_pool_size; | |
| 19296 | 23 | } | |
| 19297 | |||
| 19298 | /** Calculates the key number used inside MySQL for an Innobase index. We | ||
| 19299 | will first check the "index translation table" for a match of the index to | ||
| 19300 | get the index number. If there does not exist an "index translation table", | ||
| 19301 | or not able to find the index in the translation table, then we will fall | ||
| 19302 | back to the traditional way of looping through dict_index_t list to find a | ||
| 19303 | match. In this case, we have to take into account if we generated a | ||
| 19304 | default clustered index for the table | ||
| 19305 | @return the key number used inside MySQL */ | ||
| 19306 | 914422 | static int innobase_get_mysql_key_number_for_index( | |
| 19307 | INNOBASE_SHARE *share, /*!< in: share structure for index | ||
| 19308 | translation table. */ | ||
| 19309 | const TABLE *table, /*!< in: table in MySQL data | ||
| 19310 | dictionary */ | ||
| 19311 | dict_table_t *ib_table, /*!< in: table in InnoDB data | ||
| 19312 | dictionary */ | ||
| 19313 | const dict_index_t *index) /*!< in: index */ | ||
| 19314 | { | ||
| 19315 | const dict_index_t *ind; | ||
| 19316 | unsigned int i; | ||
| 19317 | |||
| 19318 | /* If index does not belong to the table object of share structure | ||
| 19319 | (ib_table comes from the share structure) search the index->table | ||
| 19320 | object instead */ | ||
| 19321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 914422 times.
|
914422 | if (index->table != ib_table) { |
| 19322 | ✗ | i = 0; | |
| 19323 | ✗ | ind = index->table->first_index(); | |
| 19324 | |||
| 19325 | ✗ | while (index != ind) { | |
| 19326 | ✗ | ind = ind->next(); | |
| 19327 | ✗ | i++; | |
| 19328 | } | ||
| 19329 | |||
| 19330 | ✗ | if (row_table_got_default_clust_index(index->table)) { | |
| 19331 | ✗ | ut_a(i > 0); | |
| 19332 | ✗ | i--; | |
| 19333 | } | ||
| 19334 | |||
| 19335 | ✗ | return (i); | |
| 19336 | } | ||
| 19337 | |||
| 19338 | /* If index translation table exists, we will first check | ||
| 19339 | the index through index translation table for a match. */ | ||
| 19340 |
1/2✓ Branch 0 taken 914422 times.
✗ Branch 1 not taken.
|
914422 | if (share->idx_trans_tbl.index_mapping != nullptr) { |
| 19341 |
1/2✓ Branch 0 taken 915076 times.
✗ Branch 1 not taken.
|
915076 | for (i = 0; i < share->idx_trans_tbl.index_count; i++) { |
| 19342 |
2/2✓ Branch 0 taken 914422 times.
✓ Branch 1 taken 654 times.
|
915076 | if (share->idx_trans_tbl.index_mapping[i] == index) { |
| 19343 | 914422 | return (i); | |
| 19344 | } | ||
| 19345 | } | ||
| 19346 | |||
| 19347 | /* Print an error message if we cannot find the index | ||
| 19348 | in the "index translation table". */ | ||
| 19349 | ✗ | if (index->is_committed()) { | |
| 19350 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX, index->name()); | |
| 19351 | } | ||
| 19352 | } | ||
| 19353 | |||
| 19354 | /* If we do not have an "index translation table", or not able | ||
| 19355 | to find the index in the translation table, we'll directly find | ||
| 19356 | matching index with information from mysql TABLE structure and | ||
| 19357 | InnoDB dict_index_t list */ | ||
| 19358 | ✗ | for (i = 0; i < table->s->keys; i++) { | |
| 19359 | ✗ | ind = dict_table_get_index_on_name(ib_table, table->key_info[i].name); | |
| 19360 | |||
| 19361 | ✗ | if (index == ind) { | |
| 19362 | ✗ | return (i); | |
| 19363 | } | ||
| 19364 | } | ||
| 19365 | |||
| 19366 | /* Loop through each index of the table and lock them */ | ||
| 19367 | ✗ | for (ind = ib_table->first_index(); ind != nullptr; ind = ind->next()) { | |
| 19368 | ✗ | if (index == ind) { | |
| 19369 | /* Temp index is internal to InnoDB, that is | ||
| 19370 | not present in the MySQL index list, so no | ||
| 19371 | need to print such mismatch warning. */ | ||
| 19372 | ✗ | if (index->is_committed()) { | |
| 19373 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_INTERNAL_INDEX, index->name()); | |
| 19374 | } | ||
| 19375 | ✗ | return (-1); | |
| 19376 | } | ||
| 19377 | } | ||
| 19378 | |||
| 19379 | ✗ | ut_error; | |
| 19380 | } | ||
| 19381 | |||
| 19382 | /** Calculate Record Per Key value. | ||
| 19383 | Need to exclude the NULL value if innodb_stats_method is set to "nulls_ignored" | ||
| 19384 | @param[in] index InnoDB index. | ||
| 19385 | @param[in] i The column we are calculating rec per key. | ||
| 19386 | @param[in] records Estimated total records. | ||
| 19387 | @return estimated record per key value */ | ||
| 19388 | 41934152 | rec_per_key_t innodb_rec_per_key(const dict_index_t *index, ulint i, | |
| 19389 | ha_rows records) { | ||
| 19390 | rec_per_key_t rec_per_key; | ||
| 19391 | uint64_t n_diff; | ||
| 19392 | |||
| 19393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41934169 times.
|
41934152 | ut_a(index->table->stat_initialized); |
| 19394 | |||
| 19395 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41934153 times.
|
41934169 | ut_ad(i < dict_index_get_n_unique(index)); |
| 19396 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41934200 times.
|
41934153 | ut_ad(!dict_index_is_spatial(index)); |
| 19397 | |||
| 19398 |
2/2✓ Branch 0 taken 5522832 times.
✓ Branch 1 taken 36411368 times.
|
41934200 | if (records == 0) { |
| 19399 | /* "Records per key" is meaningless for empty tables. | ||
| 19400 | Return 1.0 because that is most convenient to the Optimizer. */ | ||
| 19401 | 5522832 | return (1.0); | |
| 19402 | } | ||
| 19403 | |||
| 19404 | 36411368 | n_diff = index->stat_n_diff_key_vals[i]; | |
| 19405 | |||
| 19406 |
2/2✓ Branch 0 taken 5780419 times.
✓ Branch 1 taken 30630949 times.
|
36411368 | if (n_diff == 0) { |
| 19407 | 5780419 | rec_per_key = static_cast<rec_per_key_t>(records); | |
| 19408 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 30630941 times.
|
30630949 | } else if (srv_innodb_stats_method == SRV_STATS_NULLS_IGNORED) { |
| 19409 | uint64_t n_null; | ||
| 19410 | uint64_t n_non_null; | ||
| 19411 | |||
| 19412 | 8 | n_non_null = index->stat_n_non_null_key_vals[i]; | |
| 19413 | |||
| 19414 | /* In theory, index->stat_n_non_null_key_vals[i] | ||
| 19415 | should always be less than the number of records. | ||
| 19416 | Since this is statistics value, the value could | ||
| 19417 | have slight discrepancy. But we will make sure | ||
| 19418 | the number of null values is not a negative number. */ | ||
| 19419 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (records < n_non_null) { |
| 19420 | ✗ | n_null = 0; | |
| 19421 | } else { | ||
| 19422 | 8 | n_null = records - n_non_null; | |
| 19423 | } | ||
| 19424 | |||
| 19425 | /* If the number of NULL values is the same as or | ||
| 19426 | large than that of the distinct values, we could | ||
| 19427 | consider that the table consists mostly of NULL value. | ||
| 19428 | Set rec_per_key to 1. */ | ||
| 19429 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (n_diff <= n_null) { |
| 19430 | 8 | rec_per_key = 1.0; | |
| 19431 | } else { | ||
| 19432 | /* Need to exclude rows with NULL values from | ||
| 19433 | rec_per_key calculation */ | ||
| 19434 | ✗ | rec_per_key = | |
| 19435 | ✗ | static_cast<rec_per_key_t>(records - n_null) / (n_diff - n_null); | |
| 19436 | } | ||
| 19437 | } else { | ||
| 19438 | #ifdef UNIV_DEBUG | ||
| 19439 |
2/2✓ Branch 0 taken 4562853 times.
✓ Branch 1 taken 26068088 times.
|
30630941 | if (!index->table->is_dd_table) { |
| 19440 |
2/2✓ Branch 0 taken 4457052 times.
✓ Branch 1 taken 105801 times.
|
4562853 | DEBUG_SYNC_C("after_checking_for_0"); |
| 19441 | } | ||
| 19442 | #endif /* UNIV_DEBUG */ | ||
| 19443 | 30630981 | rec_per_key = static_cast<rec_per_key_t>(records) / n_diff; | |
| 19444 | } | ||
| 19445 | |||
| 19446 |
2/2✓ Branch 0 taken 2749767 times.
✓ Branch 1 taken 33661641 times.
|
36411408 | if (rec_per_key < 1.0) { |
| 19447 | /* Values below 1.0 are meaningless and must be due to the | ||
| 19448 | stats being imprecise. */ | ||
| 19449 | 2749767 | rec_per_key = 1.0; | |
| 19450 | } | ||
| 19451 | |||
| 19452 | 36411408 | return (rec_per_key); | |
| 19453 | } | ||
| 19454 | |||
| 19455 | /** Read the auto_increment counter of a table, using the AUTOINC lock | ||
| 19456 | irrespective of innodb_autoinc_lock_mode. | ||
| 19457 | @param[in,out] innodb_table InnoDB table object | ||
| 19458 | @param[in] print_note Print note if not an I_S query. | ||
| 19459 | @return the autoinc value */ | ||
| 19460 | 17649 | static ulonglong innobase_peek_autoinc(dict_table_t *innodb_table, | |
| 19461 | bool print_note) { | ||
| 19462 | ulonglong auto_inc; | ||
| 19463 | |||
| 19464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17649 times.
|
17649 | ut_a(innodb_table != nullptr); |
| 19465 | |||
| 19466 | 17649 | dict_table_autoinc_lock(innodb_table); | |
| 19467 | |||
| 19468 | 17649 | auto_inc = dict_table_autoinc_read(innodb_table); | |
| 19469 | |||
| 19470 |
3/4✓ Branch 0 taken 3008 times.
✓ Branch 1 taken 14641 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3008 times.
|
17649 | if (auto_inc == 0 && print_note) { |
| 19471 | ✗ | ib::info(ER_IB_MSG_569) << "AUTOINC next value generation is disabled for " | |
| 19472 | ✗ | << innodb_table->name; | |
| 19473 | } | ||
| 19474 | |||
| 19475 | 17649 | dict_table_autoinc_unlock(innodb_table); | |
| 19476 | |||
| 19477 | 17649 | return (auto_inc); | |
| 19478 | } | ||
| 19479 | |||
| 19480 | /** Calculate delete length statistic. | ||
| 19481 | @param[in] ib_table table object | ||
| 19482 | @param[in,out] stats stats structure to hold calculated values | ||
| 19483 | @param[in,out] thd user thread handle (for issuing warnings) */ | ||
| 19484 | 24107 | static void calculate_delete_length_stat(const dict_table_t *ib_table, | |
| 19485 | ha_statistics *stats, THD *thd) { | ||
| 19486 | uintmax_t avail_space; | ||
| 19487 | |||
| 19488 | 24107 | avail_space = fsp_get_available_space_in_free_extents(ib_table->space); | |
| 19489 | |||
| 19490 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24107 times.
|
24107 | if (avail_space == UINTMAX_MAX) { |
| 19491 | char errbuf[MYSYS_STRERROR_SIZE]; | ||
| 19492 | ✗ | std::ostringstream err_msg; | |
| 19493 | ✗ | err_msg << "InnoDB: Trying to get the free space for table " | |
| 19494 | ✗ | << ib_table->name | |
| 19495 | << " but its tablespace has been" | ||
| 19496 | " discarded or the .ibd file is missing. Setting" | ||
| 19497 | ✗ | " the free space to zero. (errno: " | |
| 19498 | ✗ | << errno << " - " << my_strerror(errbuf, sizeof(errbuf), errno) | |
| 19499 | ✗ | << ")"; | |
| 19500 | |||
| 19501 | ✗ | push_warning(thd, Sql_condition::SL_WARNING, ER_CANT_GET_STAT, | |
| 19502 | ✗ | err_msg.str().c_str()); | |
| 19503 | |||
| 19504 | ✗ | stats->delete_length = 0; | |
| 19505 | ✗ | } else { | |
| 19506 | 24107 | stats->delete_length = avail_space * 1024; | |
| 19507 | } | ||
| 19508 | 24107 | } | |
| 19509 | |||
| 19510 | /** Calculate stats based on index size. | ||
| 19511 | @param[in] ib_table table object | ||
| 19512 | @param[in] n_rows number of rows | ||
| 19513 | @param[in] stat_clustered_index_size clustered index size | ||
| 19514 | @param[in] stat_sum_of_other_index_sizes sum of non-clustered index sizes | ||
| 19515 | @param[in,out] stats the stats structure to hold | ||
| 19516 | calculated values */ | ||
| 19517 | 8270185 | static void calculate_index_size_stats(const dict_table_t *ib_table, | |
| 19518 | uint64_t n_rows, | ||
| 19519 | ulint stat_clustered_index_size, | ||
| 19520 | ulint stat_sum_of_other_index_sizes, | ||
| 19521 | ha_statistics *stats) { | ||
| 19522 |
1/2✓ Branch 0 taken 8270349 times.
✗ Branch 1 not taken.
|
8270185 | const page_size_t &page_size = dict_table_page_size(ib_table); |
| 19523 | |||
| 19524 | 8270349 | stats->records = static_cast<ha_rows>(n_rows); | |
| 19525 | 8270322 | stats->data_file_length = | |
| 19526 |
1/2✓ Branch 0 taken 8270322 times.
✗ Branch 1 not taken.
|
8270349 | static_cast<ulonglong>(stat_clustered_index_size) * page_size.physical(); |
| 19527 | 8270356 | stats->index_file_length = | |
| 19528 | 8270356 | static_cast<ulonglong>(stat_sum_of_other_index_sizes) * | |
| 19529 |
1/2✓ Branch 0 taken 8270356 times.
✗ Branch 1 not taken.
|
8270322 | page_size.physical(); |
| 19530 |
2/2✓ Branch 0 taken 340054 times.
✓ Branch 1 taken 7930302 times.
|
8270356 | if (stats->records == 0) { |
| 19531 | 340054 | stats->mean_rec_length = 0; | |
| 19532 | } else { | ||
| 19533 | 7930302 | stats->mean_rec_length = | |
| 19534 | 7930302 | static_cast<ulong>(stats->data_file_length / stats->records); | |
| 19535 | } | ||
| 19536 | 8270356 | } | |
| 19537 | |||
| 19538 | /** Estimate what percentage of an index's pages are cached in the buffer pool | ||
| 19539 | @param[in] index index whose pages to look up | ||
| 19540 | @return a real number in [0.0, 1.0] designating the percentage of cached pages | ||
| 19541 | */ | ||
| 19542 | 23248922 | inline double index_pct_cached(const dict_index_t *index) { | |
| 19543 | 23248922 | const ulint n_leaf = index->stat_n_leaf_pages; | |
| 19544 | |||
| 19545 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23248922 times.
|
23248922 | if (n_leaf == 0) { |
| 19546 | ✗ | return (0.0); | |
| 19547 | } | ||
| 19548 | |||
| 19549 | const uint64_t n_in_mem = | ||
| 19550 |
1/2✓ Branch 0 taken 23249072 times.
✗ Branch 1 not taken.
|
23248922 | buf_stat_per_index->get(index_id_t(index->space, index->id)); |
| 19551 | |||
| 19552 | 23249072 | const double ratio = static_cast<double>(n_in_mem) / n_leaf; | |
| 19553 | |||
| 19554 | 23249072 | return (std::max(std::min(ratio, 1.0), 0.0)); | |
| 19555 | } | ||
| 19556 | |||
| 19557 | /** Returns statistics information of the table to the MySQL interpreter, in | ||
| 19558 | various fields of the handle object. | ||
| 19559 | @param[in] flag what information is requested | ||
| 19560 | @param[in] is_analyze True if called from "::analyze()". | ||
| 19561 | @return HA_ERR_* error code or 0 */ | ||
| 19562 | 9310193 | int ha_innobase::info_low(uint flag, bool is_analyze) { | |
| 19563 | dict_table_t *ib_table; | ||
| 19564 | uint64_t n_rows; | ||
| 19565 | |||
| 19566 |
1/2✓ Branch 0 taken 9310504 times.
✗ Branch 1 not taken.
|
9310193 | DBUG_TRACE; |
| 19567 | |||
| 19568 |
3/4✓ Branch 0 taken 9134584 times.
✓ Branch 1 taken 175920 times.
✓ Branch 2 taken 9134607 times.
✗ Branch 3 not taken.
|
9310504 | DEBUG_SYNC_C("ha_innobase_info_low"); |
| 19569 | |||
| 19570 | /* If we are forcing recovery at a high level, we will suppress | ||
| 19571 | statistics calculation on tables, because that may crash the | ||
| 19572 | server if an index is badly corrupted. */ | ||
| 19573 | |||
| 19574 | /* We do not know if MySQL can call this function before calling | ||
| 19575 | external_lock(). To be safe, update the thd of the current table | ||
| 19576 | handle. */ | ||
| 19577 | |||
| 19578 |
2/4✓ Branch 0 taken 9310517 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9310501 times.
✗ Branch 3 not taken.
|
9310527 | update_thd(ha_thd()); |
| 19579 | |||
| 19580 | 9310501 | m_prebuilt->trx->op_info = (char *)"returning various info to MySQL"; | |
| 19581 | |||
| 19582 | 9310501 | ib_table = m_prebuilt->table; | |
| 19583 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9310481 times.
|
9310501 | assert(ib_table->n_ref_count > 0); |
| 19584 | |||
| 19585 |
2/2✓ Branch 0 taken 152560 times.
✓ Branch 1 taken 9157921 times.
|
9310481 | if (flag & HA_STATUS_TIME) { |
| 19586 |
4/4✓ Branch 0 taken 140187 times.
✓ Branch 1 taken 12373 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 140115 times.
|
152560 | if (is_analyze || innobase_stats_on_metadata) { |
| 19587 | dict_stats_upd_option_t opt; | ||
| 19588 | dberr_t ret; | ||
| 19589 | |||
| 19590 | 12445 | m_prebuilt->trx->op_info = "updating table statistics"; | |
| 19591 | |||
| 19592 |
3/4✓ Branch 0 taken 12445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12225 times.
✓ Branch 3 taken 220 times.
|
12445 | if (dict_stats_is_persistent_enabled(ib_table)) { |
| 19593 |
2/2✓ Branch 0 taken 12153 times.
✓ Branch 1 taken 72 times.
|
12225 | if (is_analyze) { |
| 19594 | /* If this table is already queued for background analyze, remove it | ||
| 19595 | from the queue as we are about to do the same */ | ||
| 19596 |
2/2✓ Branch 0 taken 12151 times.
✓ Branch 1 taken 2 times.
|
12153 | if (!srv_read_only_mode) { |
| 19597 |
1/2✓ Branch 0 taken 12151 times.
✗ Branch 1 not taken.
|
12151 | dict_mutex_enter_for_mysql(); |
| 19598 |
1/2✓ Branch 0 taken 12151 times.
✗ Branch 1 not taken.
|
12151 | dict_stats_recalc_pool_del(ib_table); |
| 19599 |
1/2✓ Branch 0 taken 12151 times.
✗ Branch 1 not taken.
|
12151 | dict_mutex_exit_for_mysql(); |
| 19600 | } | ||
| 19601 | 12153 | opt = DICT_STATS_RECALC_PERSISTENT; | |
| 19602 | } else { | ||
| 19603 | /* This is e.g. 'SHOW INDEXES', fetch | ||
| 19604 | the persistent stats from disk. */ | ||
| 19605 | 72 | opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY; | |
| 19606 | } | ||
| 19607 | } else { | ||
| 19608 | 220 | opt = DICT_STATS_RECALC_TRANSIENT; | |
| 19609 | } | ||
| 19610 | |||
| 19611 |
2/4✓ Branch 0 taken 12445 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12445 times.
|
12445 | ut_ad(!dict_sys_mutex_own()); |
| 19612 |
1/2✓ Branch 0 taken 12445 times.
✗ Branch 1 not taken.
|
12445 | ret = dict_stats_update(ib_table, opt); |
| 19613 | |||
| 19614 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12445 times.
|
12445 | if (ret != DB_SUCCESS) { |
| 19615 | ✗ | m_prebuilt->trx->op_info = ""; | |
| 19616 | ✗ | return HA_ERR_GENERIC; | |
| 19617 | } | ||
| 19618 | |||
| 19619 | 12445 | m_prebuilt->trx->op_info = "returning various info to MySQL"; | |
| 19620 | } | ||
| 19621 | |||
| 19622 | 152560 | stats.update_time = (ulong)std::chrono::system_clock::to_time_t( | |
| 19623 | 305120 | ib_table->update_time.load()); | |
| 19624 | } | ||
| 19625 | |||
| 19626 |
2/2✓ Branch 0 taken 8266933 times.
✓ Branch 1 taken 1043548 times.
|
9310481 | if (flag & HA_STATUS_VARIABLE) { |
| 19627 | ulint stat_clustered_index_size; | ||
| 19628 | ulint stat_sum_of_other_index_sizes; | ||
| 19629 | |||
| 19630 |
2/2✓ Branch 0 taken 40935 times.
✓ Branch 1 taken 8225998 times.
|
8266933 | if (!(flag & HA_STATUS_NO_LOCK)) { |
| 19631 |
1/2✓ Branch 0 taken 40935 times.
✗ Branch 1 not taken.
|
40935 | dict_table_stats_lock(ib_table, RW_S_LATCH); |
| 19632 | } | ||
| 19633 | |||
| 19634 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8266765 times.
|
8266933 | ut_a(ib_table->stat_initialized); |
| 19635 | |||
| 19636 | 8266765 | n_rows = ib_table->stat_n_rows; | |
| 19637 | |||
| 19638 | 8266765 | stat_clustered_index_size = ib_table->stat_clustered_index_size; | |
| 19639 | |||
| 19640 | 8266765 | stat_sum_of_other_index_sizes = ib_table->stat_sum_of_other_index_sizes; | |
| 19641 | |||
| 19642 |
2/2✓ Branch 0 taken 40935 times.
✓ Branch 1 taken 8225830 times.
|
8266765 | if (!(flag & HA_STATUS_NO_LOCK)) { |
| 19643 |
1/2✓ Branch 0 taken 40935 times.
✗ Branch 1 not taken.
|
40935 | dict_table_stats_unlock(ib_table, RW_S_LATCH); |
| 19644 | } | ||
| 19645 | |||
| 19646 | /* | ||
| 19647 | The MySQL optimizer seems to assume in a left join that n_rows | ||
| 19648 | is an accurate estimate if it is zero. Of course, it is not, | ||
| 19649 | since we do not have any locks on the rows yet at this phase. | ||
| 19650 | Since SHOW TABLE STATUS seems to call this function with the | ||
| 19651 | HA_STATUS_TIME flag set, while the left join optimizer does not | ||
| 19652 | set that flag, we add one to a zero value if the flag is not | ||
| 19653 | set. That way SHOW TABLE STATUS will show the best estimate, | ||
| 19654 | while the optimizer never sees the table empty. | ||
| 19655 | However, if it is internal temporary table used by optimizer, | ||
| 19656 | the count should be accurate */ | ||
| 19657 | |||
| 19658 |
4/4✓ Branch 0 taken 2018218 times.
✓ Branch 1 taken 6248547 times.
✓ Branch 2 taken 1897106 times.
✓ Branch 3 taken 121112 times.
|
8266765 | if (n_rows == 0 && !(flag & HA_STATUS_TIME) && |
| 19659 |
2/2✓ Branch 0 taken 1679726 times.
✓ Branch 1 taken 217380 times.
|
1897106 | table_share->table_category != TABLE_CATEGORY_TEMPORARY) { |
| 19660 | 1679726 | n_rows++; | |
| 19661 | } | ||
| 19662 | |||
| 19663 | 8266765 | stats.records = (ha_rows)n_rows; | |
| 19664 | 8266765 | stats.deleted = 0; | |
| 19665 | |||
| 19666 |
1/2✓ Branch 0 taken 8266928 times.
✗ Branch 1 not taken.
|
8266765 | calculate_index_size_stats(ib_table, n_rows, stat_clustered_index_size, |
| 19667 | stat_sum_of_other_index_sizes, &stats); | ||
| 19668 | |||
| 19669 | /* Since fsp_get_available_space_in_free_extents() is | ||
| 19670 | acquiring latches inside InnoDB, we do not call it if we | ||
| 19671 | are asked by MySQL to avoid locking. Another reason to | ||
| 19672 | avoid the call is that it uses quite a lot of CPU. | ||
| 19673 | See Bug#38185. */ | ||
| 19674 |
4/4✓ Branch 0 taken 40935 times.
✓ Branch 1 taken 8225993 times.
✓ Branch 2 taken 20662 times.
✓ Branch 3 taken 20273 times.
|
8266928 | if (flag & HA_STATUS_NO_LOCK || !(flag & HA_STATUS_VARIABLE_EXTRA)) { |
| 19675 | /* We do not update delete_length if no | ||
| 19676 | locking is requested so the "old" value can | ||
| 19677 | remain. delete_length is initialized to 0 in | ||
| 19678 | the ha_statistics' constructor. Also we only | ||
| 19679 | need delete_length to be set when | ||
| 19680 | HA_STATUS_VARIABLE_EXTRA is set */ | ||
| 19681 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20662 times.
|
20662 | } else if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { |
| 19682 | /* Avoid accessing the tablespace if | ||
| 19683 | innodb_crash_recovery is set to a high value. */ | ||
| 19684 | ✗ | stats.delete_length = 0; | |
| 19685 | } else { | ||
| 19686 |
2/4✓ Branch 0 taken 20662 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20602 times.
✗ Branch 3 not taken.
|
20662 | calculate_delete_length_stat(ib_table, &stats, ha_thd()); |
| 19687 | } | ||
| 19688 | |||
| 19689 | 8266868 | stats.check_time = 0; | |
| 19690 | 8266868 | stats.mrr_length_per_rec = ref_length + sizeof(void *); | |
| 19691 | } | ||
| 19692 | |||
| 19693 | /* Verify the number of indexes in InnoDB and MySQL | ||
| 19694 | matches up. If m_prebuilt->clust_index_was_generated | ||
| 19695 | holds, InnoDB defines GEN_CLUST_INDEX internally. */ | ||
| 19696 |
1/2✓ Branch 0 taken 9310254 times.
✗ Branch 1 not taken.
|
9310416 | ulint num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) - |
| 19697 | 9310254 | m_prebuilt->clust_index_was_generated; | |
| 19698 |
2/2✓ Branch 0 taken 5719 times.
✓ Branch 1 taken 9304535 times.
|
9310254 | if (table->s->keys < num_innodb_index) { |
| 19699 | /* If there are too many indexes defined | ||
| 19700 | inside InnoDB, ignore those that are being | ||
| 19701 | created, because MySQL will only consider | ||
| 19702 | the fully built indexes here. */ | ||
| 19703 | |||
| 19704 |
6/10✓ Branch 0 taken 5719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5719 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27549 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 33268 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 27549 times.
✓ Branch 9 taken 5719 times.
|
33268 | for (const dict_index_t *index : ib_table->indexes) { |
| 19705 | /* First, online index creation is | ||
| 19706 | completed inside InnoDB, and then | ||
| 19707 | MySQL attempts to upgrade the | ||
| 19708 | meta-data lock so that it can rebuild | ||
| 19709 | the .frm file. If we get here in that | ||
| 19710 | time frame, dict_index_is_online_ddl() | ||
| 19711 | would not hold and the index would | ||
| 19712 | still not be included in TABLE_SHARE. */ | ||
| 19713 |
3/4✓ Branch 0 taken 27549 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
✓ Branch 3 taken 27407 times.
|
27549 | if (!index->is_committed()) { |
| 19714 | 142 | num_innodb_index--; | |
| 19715 | } | ||
| 19716 | } | ||
| 19717 | |||
| 19718 |
4/4✓ Branch 0 taken 5586 times.
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 5586 times.
✓ Branch 3 taken 133 times.
|
11305 | if (table->s->keys < num_innodb_index && |
| 19719 |
2/4✓ Branch 0 taken 5586 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5586 times.
✗ Branch 3 not taken.
|
5586 | innobase_fts_check_doc_id_index(ib_table, nullptr, nullptr) == |
| 19720 | FTS_EXIST_DOC_ID_INDEX) { | ||
| 19721 | 5586 | num_innodb_index--; | |
| 19722 | } | ||
| 19723 | } | ||
| 19724 | |||
| 19725 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9310254 times.
|
9310254 | if (table->s->keys != num_innodb_index) { |
| 19726 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_IDX_CNT_MORE_THAN_DEFINED_IN_MYSQL, | |
| 19727 | ib_table->name.m_name, num_innodb_index, table->s->keys); | ||
| 19728 | } | ||
| 19729 | |||
| 19730 |
2/2✓ Branch 0 taken 169881 times.
✓ Branch 1 taken 9140373 times.
|
9310254 | if (!(flag & HA_STATUS_NO_LOCK)) { |
| 19731 |
1/2✓ Branch 0 taken 169881 times.
✗ Branch 1 not taken.
|
169881 | dict_table_stats_lock(ib_table, RW_S_LATCH); |
| 19732 | } | ||
| 19733 | |||
| 19734 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 9310204 times.
|
9310254 | ut_a(ib_table->stat_initialized); |
| 19735 | |||
| 19736 | 9310204 | const dict_index_t *pk = UT_LIST_GET_FIRST(ib_table->indexes); | |
| 19737 | |||
| 19738 |
2/2✓ Branch 0 taken 23283749 times.
✓ Branch 1 taken 9310547 times.
|
32594296 | for (uint i = 0; i < table->s->keys; i++) { |
| 19739 | ulong j; | ||
| 19740 | /* We could get index quickly through internal | ||
| 19741 | index mapping with the index translation table. | ||
| 19742 | The identity of index (match up index name with | ||
| 19743 | that of table->key_info[i]) is already verified in | ||
| 19744 | innobase_get_index(). */ | ||
| 19745 |
1/2✓ Branch 0 taken 23284205 times.
✗ Branch 1 not taken.
|
23283749 | dict_index_t *index = innobase_get_index(i); |
| 19746 | |||
| 19747 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23284205 times.
|
23284205 | if (index == nullptr) { |
| 19748 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_IDX_CNT_FEWER_THAN_DEFINED_IN_MYSQL, | |
| 19749 | ib_table->name.m_name, TROUBLESHOOTING_MSG); | ||
| 19750 | ✗ | break; | |
| 19751 | } | ||
| 19752 | |||
| 19753 | 23284205 | KEY *key = &table->key_info[i]; | |
| 19754 | |||
| 19755 | double pct_cached; | ||
| 19756 | |||
| 19757 | /* We do not maintain stats for fulltext or spatial indexes. | ||
| 19758 | Thus, we can't calculate pct_cached below because we need | ||
| 19759 | dict_index_t::stat_n_leaf_pages for that. See | ||
| 19760 | dict_stats_should_ignore_index(). */ | ||
| 19761 |
4/4✓ Branch 0 taken 23268726 times.
✓ Branch 1 taken 15479 times.
✓ Branch 2 taken 19679 times.
✓ Branch 3 taken 23249047 times.
|
23284205 | if ((key->flags & HA_FULLTEXT) || (key->flags & HA_SPATIAL)) { |
| 19762 | 35158 | pct_cached = IN_MEMORY_ESTIMATE_UNKNOWN; | |
| 19763 | } else { | ||
| 19764 |
1/2✓ Branch 0 taken 23248856 times.
✗ Branch 1 not taken.
|
23249047 | pct_cached = index_pct_cached(index); |
| 19765 | } | ||
| 19766 | |||
| 19767 | 23284014 | key->set_in_memory_estimate(pct_cached); | |
| 19768 | |||
| 19769 |
2/2✓ Branch 0 taken 7770136 times.
✓ Branch 1 taken 15513978 times.
|
23284114 | if (index == pk) { |
| 19770 | 7770136 | stats.table_in_mem_estimate = pct_cached; | |
| 19771 | } | ||
| 19772 | |||
| 19773 |
2/2✓ Branch 0 taken 10113158 times.
✓ Branch 1 taken 13170956 times.
|
23284114 | if (flag & HA_STATUS_CONST) { |
| 19774 |
2/2✓ Branch 0 taken 2732 times.
✓ Branch 1 taken 10110417 times.
|
10113158 | if (!key->supports_records_per_key()) { |
| 19775 | 2732 | continue; | |
| 19776 | } | ||
| 19777 | |||
| 19778 |
2/2✓ Branch 0 taken 20963346 times.
✓ Branch 1 taken 10110404 times.
|
31073750 | for (j = 0; j < key->actual_key_parts; j++) { |
| 19779 |
4/4✓ Branch 0 taken 20958293 times.
✓ Branch 1 taken 5053 times.
✓ Branch 2 taken 1411 times.
✓ Branch 3 taken 20956882 times.
|
20963346 | if ((key->flags & HA_FULLTEXT) || (key->flags & HA_SPATIAL)) { |
| 19780 | /* The record per key does not apply to | ||
| 19781 | FTS or Spatial indexes. */ | ||
| 19782 | 6464 | key->set_records_per_key(j, 1.0f); | |
| 19783 | 6470 | continue; | |
| 19784 | } | ||
| 19785 | |||
| 19786 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20956882 times.
|
20956882 | if (j + 1 > index->n_uniq) { |
| 19787 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_IDX_COLUMN_CNT_DIFF, index->name(), | |
| 19788 | ib_table->name.m_name, (unsigned long)index->n_uniq, j + 1, | ||
| 19789 | TROUBLESHOOTING_MSG); | ||
| 19790 | ✗ | break; | |
| 19791 | } | ||
| 19792 | |||
| 19793 | /* innodb_rec_per_key() will use | ||
| 19794 | index->stat_n_diff_key_vals[] and the value we | ||
| 19795 | pass index->table->stat_n_rows. Both are | ||
| 19796 | calculated by ANALYZE and by the background | ||
| 19797 | stats gathering thread (which kicks in when too | ||
| 19798 | much of the table has been changed). In | ||
| 19799 | addition table->stat_n_rows is adjusted with | ||
| 19800 | each DML (e.g. ++ on row insert). Those | ||
| 19801 | adjustments are not MVCC'ed and not even | ||
| 19802 | reversed on rollback. So, | ||
| 19803 | index->stat_n_diff_key_vals[] and | ||
| 19804 | index->table->stat_n_rows could have been | ||
| 19805 | calculated at different time. This is | ||
| 19806 | acceptable. */ | ||
| 19807 | const rec_per_key_t rec_per_key = | ||
| 19808 |
1/2✓ Branch 0 taken 20956853 times.
✗ Branch 1 not taken.
|
20956882 | innodb_rec_per_key(index, (ulint)j, index->table->stat_n_rows); |
| 19809 | |||
| 19810 | 20956853 | key->set_records_per_key(j, rec_per_key); | |
| 19811 | |||
| 19812 | /* The code below is legacy and should be | ||
| 19813 | removed together with this comment once we | ||
| 19814 | are sure the new floating point rec_per_key, | ||
| 19815 | set via set_records_per_key(), works fine. */ | ||
| 19816 | |||
| 19817 | ulong rec_per_key_int = static_cast<ulong>( | ||
| 19818 |
1/2✓ Branch 0 taken 20956863 times.
✗ Branch 1 not taken.
|
20956858 | innodb_rec_per_key(index, (ulint)j, stats.records)); |
| 19819 | |||
| 19820 | /* Since MySQL seems to favor table scans | ||
| 19821 | too much over index searches, we pretend | ||
| 19822 | index selectivity is 2 times better than | ||
| 19823 | our estimate: */ | ||
| 19824 | |||
| 19825 | 20956863 | rec_per_key_int = rec_per_key_int / 2; | |
| 19826 | |||
| 19827 |
2/2✓ Branch 0 taken 15156052 times.
✓ Branch 1 taken 5800811 times.
|
20956863 | if (rec_per_key_int == 0) { |
| 19828 | 15156052 | rec_per_key_int = 1; | |
| 19829 | } | ||
| 19830 | |||
| 19831 | 20956863 | key->rec_per_key[j] = rec_per_key_int; | |
| 19832 | } | ||
| 19833 | } | ||
| 19834 | } | ||
| 19835 | |||
| 19836 |
2/2✓ Branch 0 taken 169881 times.
✓ Branch 1 taken 9140666 times.
|
9310547 | if (!(flag & HA_STATUS_NO_LOCK)) { |
| 19837 |
1/2✓ Branch 0 taken 169690 times.
✗ Branch 1 not taken.
|
169881 | dict_table_stats_unlock(ib_table, RW_S_LATCH); |
| 19838 | } | ||
| 19839 | |||
| 19840 |
2/2✓ Branch 0 taken 1736 times.
✓ Branch 1 taken 9308620 times.
|
9310356 | if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { |
| 19841 | 1736 | goto func_exit; | |
| 19842 | |||
| 19843 |
2/2✓ Branch 0 taken 914424 times.
✓ Branch 1 taken 8394196 times.
|
9308620 | } else if (flag & HA_STATUS_ERRKEY) { |
| 19844 | const dict_index_t *err_index; | ||
| 19845 | |||
| 19846 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 914424 times.
|
914424 | ut_a(m_prebuilt->trx); |
| 19847 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 914424 times.
|
914424 | ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 19848 | |||
| 19849 | 914424 | err_index = trx_get_error_index(m_prebuilt->trx); | |
| 19850 | |||
| 19851 |
2/2✓ Branch 0 taken 914422 times.
✓ Branch 1 taken 2 times.
|
914424 | if (err_index) { |
| 19852 |
1/2✓ Branch 0 taken 914422 times.
✗ Branch 1 not taken.
|
914422 | errkey = innobase_get_mysql_key_number_for_index(m_share, table, ib_table, |
| 19853 | err_index); | ||
| 19854 | } else { | ||
| 19855 | 2 | errkey = | |
| 19856 | (unsigned int)((m_prebuilt->trx->error_key_num == ULINT_UNDEFINED) | ||
| 19857 | ? ~0 | ||
| 19858 | 2 | : m_prebuilt->trx->error_key_num); | |
| 19859 | } | ||
| 19860 | } | ||
| 19861 | |||
| 19862 |
4/4✓ Branch 0 taken 9158874 times.
✓ Branch 1 taken 149746 times.
✓ Branch 2 taken 135542 times.
✓ Branch 3 taken 14204 times.
|
9308620 | if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) { |
| 19863 |
1/2✓ Branch 0 taken 14204 times.
✗ Branch 1 not taken.
|
14204 | ulonglong auto_inc_val = innobase_peek_autoinc(ib_table, true); |
| 19864 | /* Initialize autoinc value if not set. */ | ||
| 19865 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14204 times.
|
14204 | if (auto_inc_val == 0) { |
| 19866 | ✗ | dict_table_autoinc_lock(m_prebuilt->table); | |
| 19867 | ✗ | innobase_initialize_autoinc(); | |
| 19868 | ✗ | dict_table_autoinc_unlock(m_prebuilt->table); | |
| 19869 | |||
| 19870 | ✗ | auto_inc_val = innobase_peek_autoinc(ib_table, true); | |
| 19871 | } | ||
| 19872 | 14204 | stats.auto_increment_value = auto_inc_val; | |
| 19873 | } | ||
| 19874 | |||
| 19875 | 9294416 | func_exit: | |
| 19876 | 9310356 | m_prebuilt->trx->op_info = (char *)""; | |
| 19877 | |||
| 19878 | 9310356 | return 0; | |
| 19879 | 9310356 | } | |
| 19880 | |||
| 19881 | /** Returns statistics information of the table to the MySQL interpreter, | ||
| 19882 | in various fields of the handle object. | ||
| 19883 | @return HA_ERR_* error code or 0 */ | ||
| 19884 | |||
| 19885 | 9572626 | int ha_innobase::info(uint flag) /*!< in: what information is requested */ | |
| 19886 | { | ||
| 19887 | 9572626 | return (info_low(flag, false /* not ANALYZE */)); | |
| 19888 | } | ||
| 19889 | |||
| 19890 | /** Get the autoincrement for the given table id which is | ||
| 19891 | not in the cache. | ||
| 19892 | @param[in] se_private_id InnoDB table id | ||
| 19893 | @param[in] tbl_se_private_data table SE private data | ||
| 19894 | @return autoincrement value for the given table_id. */ | ||
| 19895 | 14 | static uint64_t innodb_get_auto_increment_for_uncached( | |
| 19896 | dd::Object_id se_private_id, const dd::Properties &tbl_se_private_data) { | ||
| 19897 | 14 | uint64_t autoinc = 0; | |
| 19898 | 14 | uint64_t meta_autoinc = 0; | |
| 19899 | |||
| 19900 | bool exists = | ||
| 19901 |
2/4✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
14 | tbl_se_private_data.exists(dd_table_key_strings[DD_TABLE_AUTOINC]); |
| 19902 | |||
| 19903 | /** Get the auto_increment from the table SE private data. */ | ||
| 19904 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (exists) { |
| 19905 | ✗ | tbl_se_private_data.get(dd_table_key_strings[DD_TABLE_AUTOINC], &autoinc); | |
| 19906 | } | ||
| 19907 | |||
| 19908 | /** Get the auto_increment value from innodb_dynamic_metadata | ||
| 19909 | table. */ | ||
| 19910 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | mutex_enter(&dict_persist->mutex); |
| 19911 | |||
| 19912 | 14 | DDTableBuffer *table_buffer = dict_persist->table_buffer; | |
| 19913 | |||
| 19914 | uint64_t version; | ||
| 19915 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | std::string *readmeta = table_buffer->get(se_private_id, &version); |
| 19916 | |||
| 19917 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (readmeta->length() != 0) { |
| 19918 | ✗ | PersistentTableMetadata metadata(se_private_id, version); | |
| 19919 | |||
| 19920 | ✗ | dict_table_read_dynamic_metadata( | |
| 19921 | ✗ | reinterpret_cast<const byte *>(readmeta->data()), readmeta->length(), | |
| 19922 | &metadata); | ||
| 19923 | |||
| 19924 | ✗ | meta_autoinc = metadata.get_autoinc(); | |
| 19925 | } | ||
| 19926 | |||
| 19927 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | mutex_exit(&dict_persist->mutex); |
| 19928 | |||
| 19929 | 14 | ut::delete_(readmeta); | |
| 19930 | |||
| 19931 | 14 | return (std::max(meta_autoinc, autoinc)); | |
| 19932 | } | ||
| 19933 | |||
| 19934 | /** Retrieves table statistics only for uncache table only. | ||
| 19935 | @param[in] db_name database name | ||
| 19936 | @param[in] tbl_name table name | ||
| 19937 | @param[in] norm_name tablespace name | ||
| 19938 | @param[in] se_private_id InnoDB table id | ||
| 19939 | @param[in] ts_se_private_data tablespace se private data | ||
| 19940 | @param[in] tbl_se_private_data table se private data | ||
| 19941 | @param[in] stat_flags flags used to retrieve specific stats | ||
| 19942 | @param[in,out] stats structure to save the retrieved statistics | ||
| 19943 | @return true if the stats information filled successfully | ||
| 19944 | @return false if tablespace is missing or table doesn't have persistent | ||
| 19945 | stats. */ | ||
| 19946 | 23 | static bool innodb_get_table_statistics_for_uncached( | |
| 19947 | const char *db_name, const char *tbl_name, const char *norm_name, | ||
| 19948 | dd::Object_id se_private_id, const dd::Properties &ts_se_private_data, | ||
| 19949 | const dd::Properties &tbl_se_private_data, ulint stat_flags, | ||
| 19950 | ha_statistics *stats) { | ||
| 19951 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | TableStatsRecord stat_info; |
| 19952 | space_id_t space_id; | ||
| 19953 | |||
| 19954 |
3/4✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 14 times.
|
23 | if (!row_search_table_stats(db_name, tbl_name, stat_info)) { |
| 19955 | 9 | return (false); | |
| 19956 | } | ||
| 19957 | |||
| 19958 | /** Server passes dummy ts_se_private_data for file_per_table | ||
| 19959 | tablespace. In that case, InnoDB should find the space_id using | ||
| 19960 | the tablespace name. */ | ||
| 19961 |
2/4✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
14 | bool exists = ts_se_private_data.exists(dd_space_key_strings[DD_SPACE_ID]); |
| 19962 | |||
| 19963 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (exists) { |
| 19964 | ✗ | ts_se_private_data.get(dd_space_key_strings[DD_SPACE_ID], &space_id); | |
| 19965 | } else { | ||
| 19966 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | space_id = fil_space_get_id_by_name(norm_name); |
| 19967 | |||
| 19968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (space_id == SPACE_UNKNOWN) { |
| 19969 | ✗ | return (false); | |
| 19970 | } | ||
| 19971 | } | ||
| 19972 | |||
| 19973 | fil_space_t *space; | ||
| 19974 | uint32_t fsp_flags; | ||
| 19975 | |||
| 19976 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | space = fil_space_acquire(space_id); |
| 19977 | |||
| 19978 | /** Tablespace is missing in this case. */ | ||
| 19979 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (space == nullptr) { |
| 19980 | ✗ | return (false); | |
| 19981 | } | ||
| 19982 | |||
| 19983 | 14 | fsp_flags = space->flags; | |
| 19984 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | page_size_t page_size(fsp_flags); |
| 19985 | |||
| 19986 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | if (stat_flags & HA_STATUS_VARIABLE_EXTRA) { |
| 19987 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | ulint avail_space = fsp_get_available_space_in_free_extents(space); |
| 19988 | 14 | stats->delete_length = avail_space * 1024; | |
| 19989 | } | ||
| 19990 | |||
| 19991 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | fil_space_release(space); |
| 19992 | |||
| 19993 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | if (stat_flags & HA_STATUS_AUTO) { |
| 19994 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | stats->auto_increment_value = innodb_get_auto_increment_for_uncached( |
| 19995 | se_private_id, tbl_se_private_data); | ||
| 19996 | } | ||
| 19997 | |||
| 19998 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | if (stat_flags & HA_STATUS_TIME) { |
| 19999 | 14 | stats->update_time = (time_t)NULL; | |
| 20000 | } | ||
| 20001 | |||
| 20002 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | if (stat_flags & HA_STATUS_VARIABLE) { |
| 20003 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | stats->records = static_cast<ha_rows>(stat_info.get_n_rows()); |
| 20004 | 14 | stats->data_file_length = | |
| 20005 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | static_cast<ulonglong>(stat_info.get_clustered_index_size()) * |
| 20006 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | page_size.physical(); |
| 20007 | 14 | stats->index_file_length = | |
| 20008 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | static_cast<ulonglong>(stat_info.get_sum_of_other_index_size()) * |
| 20009 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | page_size.physical(); |
| 20010 | |||
| 20011 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
|
14 | if (stats->records == 0) { |
| 20012 | 6 | stats->mean_rec_length = 0; | |
| 20013 | } else { | ||
| 20014 | 8 | stats->mean_rec_length = | |
| 20015 | 8 | static_cast<ulong>(stats->data_file_length / stats->records); | |
| 20016 | } | ||
| 20017 | } | ||
| 20018 | |||
| 20019 | 14 | return (true); | |
| 20020 | 23 | } | |
| 20021 | |||
| 20022 | 3459 | static bool innobase_get_table_statistics( | |
| 20023 | const char *db_name, const char *table_name, dd::Object_id se_private_id, | ||
| 20024 | const dd::Properties &ts_se_private_data, | ||
| 20025 | const dd::Properties &tbl_se_private_data, uint stat_flags, | ||
| 20026 | ha_statistics *stats) { | ||
| 20027 | char norm_name[FN_REFLEN]; | ||
| 20028 | dict_table_t *ib_table; | ||
| 20029 | |||
| 20030 | char buf[2 * NAME_CHAR_LEN * 5 + 2 + 1]; | ||
| 20031 | bool truncated; | ||
| 20032 |
1/2✓ Branch 0 taken 3459 times.
✗ Branch 1 not taken.
|
3459 | build_table_filename(buf, sizeof(buf), db_name, table_name, nullptr, 0, |
| 20033 | &truncated); | ||
| 20034 | |||
| 20035 |
4/8✓ Branch 0 taken 3459 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3459 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3459 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3459 times.
|
3459 | if (truncated || !normalize_table_name(norm_name, buf)) { |
| 20036 | ✗ | ut_d(ut_error); | |
| 20037 | ut_o(return true); // (HA_ERR_TOO_LONG_PATH); | ||
| 20038 | } | ||
| 20039 | |||
| 20040 | 3459 | MDL_ticket *mdl = nullptr; | |
| 20041 |
1/2✓ Branch 0 taken 3459 times.
✗ Branch 1 not taken.
|
3459 | THD *thd = current_thd; |
| 20042 | |||
| 20043 |
1/2✓ Branch 0 taken 3459 times.
✗ Branch 1 not taken.
|
3459 | ib_table = dd_table_open_on_name_in_mem(norm_name, false); |
| 20044 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 3436 times.
|
3459 | if (ib_table == nullptr) { |
| 20045 |
3/4✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 9 times.
|
23 | if (innodb_get_table_statistics_for_uncached( |
| 20046 | db_name, table_name, norm_name, se_private_id, ts_se_private_data, | ||
| 20047 | tbl_se_private_data, stat_flags, stats)) { | ||
| 20048 | 14 | return (false); | |
| 20049 | } | ||
| 20050 | |||
| 20051 | /** If the table doesn't have persistent stats then | ||
| 20052 | load the table from disk. */ | ||
| 20053 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | ib_table = dd_table_open_on_name(thd, &mdl, norm_name, false, |
| 20054 | DICT_ERR_IGNORE_NONE); | ||
| 20055 | |||
| 20056 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (ib_table == nullptr) { |
| 20057 | ✗ | return (true); | |
| 20058 | } | ||
| 20059 | } | ||
| 20060 | |||
| 20061 |
1/2✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
|
3445 | if (stat_flags & HA_STATUS_AUTO) { |
| 20062 |
1/2✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
|
3445 | stats->auto_increment_value = innobase_peek_autoinc(ib_table, false); |
| 20063 | } | ||
| 20064 | |||
| 20065 |
1/2✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
|
3445 | if (stat_flags & HA_STATUS_TIME) { |
| 20066 | 3445 | stats->update_time = static_cast<ulong>( | |
| 20067 | 3445 | std::chrono::system_clock::to_time_t(ib_table->update_time.load())); | |
| 20068 | } | ||
| 20069 | |||
| 20070 |
1/2✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
|
3445 | if (stat_flags & HA_STATUS_VARIABLE_EXTRA) { |
| 20071 |
2/4✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3445 times.
✗ Branch 3 not taken.
|
3445 | calculate_delete_length_stat(ib_table, stats, current_thd); |
| 20072 | } | ||
| 20073 | |||
| 20074 |
1/2✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
|
3445 | if (stat_flags & HA_STATUS_VARIABLE) { |
| 20075 |
1/2✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
|
3445 | dict_stats_init(ib_table); |
| 20076 | |||
| 20077 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3445 times.
|
3445 | ut_a(ib_table->stat_initialized); |
| 20078 | |||
| 20079 | /* Note it may look like ib_table->* arguments are | ||
| 20080 | redundant. If you see the usage of this call in info_low(), | ||
| 20081 | the stats can be retrieved while holding a latch if | ||
| 20082 | !HA_STATUS_NO_LOCK is passed. */ | ||
| 20083 |
1/2✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
|
3445 | calculate_index_size_stats(ib_table, ib_table->stat_n_rows, |
| 20084 | ib_table->stat_clustered_index_size, | ||
| 20085 | ib_table->stat_sum_of_other_index_sizes, stats); | ||
| 20086 | } | ||
| 20087 | |||
| 20088 |
1/2✓ Branch 0 taken 3445 times.
✗ Branch 1 not taken.
|
3445 | dd_table_close(ib_table, thd, &mdl, false); |
| 20089 | |||
| 20090 | 3445 | return (false); | |
| 20091 | } | ||
| 20092 | |||
| 20093 | 768 | static bool innobase_get_index_column_cardinality( | |
| 20094 | const char *db_name, const char *table_name, const char *index_name, uint, | ||
| 20095 | uint column_ordinal_position, dd::Object_id, ulonglong *cardinality) { | ||
| 20096 | char norm_name[FN_REFLEN]; | ||
| 20097 | dict_table_t *ib_table; | ||
| 20098 | 768 | bool failure = true; | |
| 20099 | |||
| 20100 | char buf[2 * NAME_CHAR_LEN * 5 + 2 + 1]; | ||
| 20101 | bool truncated; | ||
| 20102 |
1/2✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
|
768 | build_table_filename(buf, sizeof(buf), db_name, table_name, nullptr, 0, |
| 20103 | &truncated); | ||
| 20104 | |||
| 20105 |
4/8✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 768 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 768 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 768 times.
|
768 | if (truncated || !normalize_table_name(norm_name, buf)) { |
| 20106 | /* purecov: begin inspected */ | ||
| 20107 | ✗ | ut_d(ut_error); | |
| 20108 | ut_o(return (true)); | ||
| 20109 | /* purecov: end */ | ||
| 20110 | } | ||
| 20111 | |||
| 20112 | 768 | MDL_ticket *mdl = nullptr; | |
| 20113 |
1/2✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
|
768 | THD *thd = current_thd; |
| 20114 | |||
| 20115 |
1/2✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
|
768 | ib_table = dd_table_open_on_name_in_mem(norm_name, false); |
| 20116 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 767 times.
|
768 | if (ib_table == nullptr) { |
| 20117 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | if (row_search_index_stats(db_name, table_name, index_name, |
| 20118 | column_ordinal_position, cardinality)) { | ||
| 20119 | 1 | return (false); | |
| 20120 | } | ||
| 20121 | |||
| 20122 | /** If the table doesn't have persistent stats then | ||
| 20123 | load the table from disk. */ | ||
| 20124 | ✗ | ib_table = dd_table_open_on_name(thd, &mdl, norm_name, false, | |
| 20125 | DICT_ERR_IGNORE_NONE); | ||
| 20126 | |||
| 20127 | ✗ | if (ib_table == nullptr) { | |
| 20128 | ✗ | return (true); | |
| 20129 | } | ||
| 20130 | } | ||
| 20131 | |||
| 20132 |
2/4✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 767 times.
|
767 | if (ib_table->is_fts_aux()) { |
| 20133 | /* Server should not ask for Stats for Internal Tables */ | ||
| 20134 | ✗ | dd_table_close(ib_table, thd, &mdl, false); | |
| 20135 | ✗ | ut_d(ut_error); | |
| 20136 | ut_o(return (true)); | ||
| 20137 | } | ||
| 20138 | |||
| 20139 |
5/10✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 767 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 281 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1048 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1048 times.
✗ Branch 9 not taken.
|
1048 | for (const dict_index_t *index : ib_table->indexes) { |
| 20140 |
6/8✓ Branch 0 taken 1048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1048 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 767 times.
✓ Branch 5 taken 281 times.
✓ Branch 6 taken 767 times.
✓ Branch 7 taken 281 times.
|
1048 | if (index->is_committed() && ut_strcmp(index_name, index->name) == 0) { |
| 20141 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 698 times.
|
767 | if (ib_table->stat_initialized == 0) { |
| 20142 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | dict_stats_init(ib_table); |
| 20143 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
|
69 | ut_a(ib_table->stat_initialized != 0); |
| 20144 | } | ||
| 20145 | |||
| 20146 |
2/4✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 767 times.
✗ Branch 3 not taken.
|
767 | DEBUG_SYNC(thd, "innodb.after_init_check"); |
| 20147 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 749 times.
|
767 | if (index->type & (DICT_FTS | DICT_SPATIAL)) { |
| 20148 | /* For these indexes innodb_rec_per_key is | ||
| 20149 | fixed as 1.0 */ | ||
| 20150 | 18 | *cardinality = ib_table->stat_n_rows; | |
| 20151 | } else { | ||
| 20152 | 749 | uint64_t n_rows = ib_table->stat_n_rows; | |
| 20153 | double records = | ||
| 20154 | 1498 | (n_rows / | |
| 20155 |
1/2✓ Branch 0 taken 749 times.
✗ Branch 1 not taken.
|
749 | innodb_rec_per_key(index, (ulint)column_ordinal_position, n_rows)); |
| 20156 | 749 | *cardinality = static_cast<ulonglong>(round(records)); | |
| 20157 | } | ||
| 20158 | |||
| 20159 | 767 | failure = false; | |
| 20160 | 767 | break; | |
| 20161 | } | ||
| 20162 | } | ||
| 20163 | |||
| 20164 |
1/2✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
|
767 | dd_table_close(ib_table, thd, &mdl, false); |
| 20165 | 767 | return (failure); | |
| 20166 | } | ||
| 20167 | |||
| 20168 | 966 | static bool innobase_is_tablespace_keyring_pre_v3_encrypted( | |
| 20169 | const dd::Tablespace &tablespace, int &error) { | ||
| 20170 | 966 | error = 0; | |
| 20171 | 966 | space_id_t id = 0; | |
| 20172 | |||
| 20173 |
3/6✓ Branch 0 taken 966 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 966 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 966 times.
|
966 | ut_ad(innobase_strcasecmp(tablespace.engine().c_str(), "InnoDB") == 0); |
| 20174 | |||
| 20175 |
4/8✓ Branch 0 taken 966 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 966 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 966 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 966 times.
|
966 | if (tablespace.se_private_data().get(dd_space_key_strings[DD_SPACE_ID], &id)) |
| 20176 | ✗ | return true; | |
| 20177 | |||
| 20178 | /* Make sure tablespace is loaded. */ | ||
| 20179 |
1/2✓ Branch 0 taken 966 times.
✗ Branch 1 not taken.
|
966 | fil_space_t *space = fil_space_get(id); |
| 20180 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 957 times.
|
966 | if (space == nullptr) { |
| 20181 | 9 | error = HA_ERR_TABLESPACE_MISSING; | |
| 20182 | 9 | return false; | |
| 20183 | } | ||
| 20184 | |||
| 20185 | // If page0 was read and it has crypt - we can check if it is encrypted here | ||
| 20186 | // if crypt_data is null it means that page0 may not have yet been read - we | ||
| 20187 | // will read it in fil_space_open_if_needed and recheck if crypt_data is null | ||
| 20188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 957 times.
|
957 | if (space->crypt_data != nullptr) |
| 20189 | ✗ | return is_space_keyring_pre_v3_encrypted(space); | |
| 20190 | |||
| 20191 |
1/2✓ Branch 0 taken 957 times.
✗ Branch 1 not taken.
|
957 | fil_space_open_if_needed(space); |
| 20192 | |||
| 20193 | // We do not need to care about mutexes as this function is only called during | ||
| 20194 | // the upgrade | ||
| 20195 |
1/2✓ Branch 0 taken 957 times.
✗ Branch 1 not taken.
|
957 | return is_space_keyring_pre_v3_encrypted(space); |
| 20196 | } | ||
| 20197 | |||
| 20198 | 407974 | static bool innobase_get_tablespace_type(const dd::Tablespace &space, | |
| 20199 | Tablespace_type *space_type) { | ||
| 20200 | 407974 | space_id_t id = 0; | |
| 20201 | 407974 | uint32_t flags = 0; | |
| 20202 | |||
| 20203 |
3/6✓ Branch 0 taken 407974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 407974 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 407974 times.
|
407974 | ut_ad(innobase_strcasecmp(space.engine().c_str(), "InnoDB") == 0); |
| 20204 | |||
| 20205 |
5/12✓ Branch 0 taken 407974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 407974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 407974 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 407974 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 407974 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
1223922 | if (space.se_private_data().get(dd_space_key_strings[DD_SPACE_ID], &id) || |
| 20206 |
6/14✓ Branch 0 taken 407974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 407974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 407974 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 407974 times.
✓ Branch 8 taken 407974 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 407974 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
815948 | space.se_private_data().get(dd_space_key_strings[DD_SPACE_FLAGS], |
| 20207 | &flags)) { | ||
| 20208 | ✗ | return true; | |
| 20209 | } | ||
| 20210 | |||
| 20211 |
5/6✓ Branch 0 taken 407974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65967 times.
✓ Branch 3 taken 342007 times.
✓ Branch 4 taken 65967 times.
✓ Branch 5 taken 342007 times.
|
473941 | if (space.id() == MYSQL_TABLESPACE_DD_ID && |
| 20212 |
1/2✓ Branch 0 taken 65967 times.
✗ Branch 1 not taken.
|
65967 | id == dict_sys_t::s_dict_space_id) { |
| 20213 | 65967 | *space_type = Tablespace_type::SPACE_TYPE_DICTIONARY; | |
| 20214 |
2/2✓ Branch 0 taken 681 times.
✓ Branch 1 taken 341326 times.
|
342007 | } else if (id == TRX_SYS_SPACE) { |
| 20215 | 681 | *space_type = Tablespace_type::SPACE_TYPE_SYSTEM; | |
| 20216 |
3/4✓ Branch 0 taken 341326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 341295 times.
|
341326 | } else if (fsp_is_undo_tablespace(id)) { |
| 20217 | 31 | *space_type = Tablespace_type::SPACE_TYPE_UNDO; | |
| 20218 |
3/4✓ Branch 0 taken 341295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 341280 times.
|
341295 | } else if (fsp_is_system_temporary(id)) { |
| 20219 | 15 | *space_type = Tablespace_type::SPACE_TYPE_TEMPORARY; | |
| 20220 |
6/8✓ Branch 0 taken 330976 times.
✓ Branch 1 taken 10304 times.
✓ Branch 2 taken 330976 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 330976 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 330976 times.
✓ Branch 7 taken 10304 times.
|
341280 | } else if (fsp_is_shared_tablespace(flags) && fsp_is_ibd_tablespace(id)) { |
| 20221 | 330976 | *space_type = Tablespace_type::SPACE_TYPE_SHARED; | |
| 20222 |
2/4✓ Branch 0 taken 10304 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10304 times.
✗ Branch 3 not taken.
|
10304 | } else if (fsp_is_file_per_table(id, flags)) { |
| 20223 | 10304 | *space_type = Tablespace_type::SPACE_TYPE_IMPLICIT; | |
| 20224 | } else { | ||
| 20225 | ✗ | ut_d(ut_error); | |
| 20226 | ut_o(return true); | ||
| 20227 | } | ||
| 20228 | |||
| 20229 | 407974 | return false; | |
| 20230 | } | ||
| 20231 | |||
| 20232 | /** Get the tablespace type given the name. | ||
| 20233 | |||
| 20234 | @param[in] tablespace_name tablespace name | ||
| 20235 | @param[out] space_type type of space | ||
| 20236 | |||
| 20237 | @return Operation status. | ||
| 20238 | @retval false on success and true for failure. | ||
| 20239 | */ | ||
| 20240 | 1138942 | static bool innobase_get_tablespace_type_by_name(const char *tablespace_name, | |
| 20241 | Tablespace_type *space_type) { | ||
| 20242 |
6/6✓ Branch 0 taken 373991 times.
✓ Branch 1 taken 764951 times.
✓ Branch 2 taken 924 times.
✓ Branch 3 taken 373067 times.
✓ Branch 4 taken 764952 times.
✓ Branch 5 taken 923 times.
|
1138942 | if ((tablespace_name == nullptr && srv_file_per_table) || |
| 20243 | 764952 | (tablespace_name && | |
| 20244 |
2/2✓ Branch 0 taken 1183 times.
✓ Branch 1 taken 763769 times.
|
764952 | 0 == strcmp(tablespace_name, dict_sys_t::s_file_per_table_name))) { |
| 20245 | 374250 | *space_type = Tablespace_type::SPACE_TYPE_IMPLICIT; | |
| 20246 |
4/6✓ Branch 0 taken 924 times.
✓ Branch 1 taken 763768 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 924 times.
✓ Branch 4 taken 763770 times.
✗ Branch 5 not taken.
|
764692 | } else if ((tablespace_name == nullptr && !srv_file_per_table) || |
| 20247 | 763770 | (tablespace_name && | |
| 20248 |
2/2✓ Branch 0 taken 1009 times.
✓ Branch 1 taken 762761 times.
|
763770 | 0 == strcmp(tablespace_name, dict_sys_t::s_sys_space_name))) { |
| 20249 | 1933 | *space_type = Tablespace_type::SPACE_TYPE_SYSTEM; | |
| 20250 |
2/2✓ Branch 0 taken 759477 times.
✓ Branch 1 taken 3282 times.
|
762759 | } else if (0 == strcmp(tablespace_name, dict_sys_t::s_dd_space_name)) { |
| 20251 | 759477 | *space_type = Tablespace_type::SPACE_TYPE_DICTIONARY; | |
| 20252 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3274 times.
|
3282 | } else if (0 == strcmp(tablespace_name, dict_sys_t::s_temp_space_name)) { |
| 20253 | 8 | *space_type = Tablespace_type::SPACE_TYPE_TEMPORARY; | |
| 20254 |
1/2✓ Branch 0 taken 3276 times.
✗ Branch 1 not taken.
|
3274 | } else if (0 == strcmp(tablespace_name, |
| 20255 | 3276 | dict_sys_t::s_default_undo_space_name_1) || | |
| 20256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3276 times.
|
3276 | 0 == strcmp(tablespace_name, |
| 20257 | dict_sys_t::s_default_undo_space_name_2)) { | ||
| 20258 | /* | ||
| 20259 | TODO: This function doesn't consider user created UNDO | ||
| 20260 | tablespaces because, as of now this function is not being | ||
| 20261 | called for UNDO tablesapces. But should consider this in | ||
| 20262 | future for completeness. | ||
| 20263 | */ | ||
| 20264 | ✗ | *space_type = Tablespace_type::SPACE_TYPE_UNDO; | |
| 20265 | } else { | ||
| 20266 | 3276 | *space_type = Tablespace_type::SPACE_TYPE_SHARED; | |
| 20267 | } | ||
| 20268 | |||
| 20269 | 1138942 | return false; | |
| 20270 | } | ||
| 20271 | |||
| 20272 | 251509 | static bool innobase_get_tablespace_statistics( | |
| 20273 | const char *tablespace_name, const char *file_name, | ||
| 20274 | const dd::Properties &ts_se_private_data, ha_tablespace_statistics *stats) { | ||
| 20275 | /* Tablespace does not have space id stored. */ | ||
| 20276 |
3/6✓ Branch 0 taken 251509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251509 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 251509 times.
|
251509 | if (!ts_se_private_data.exists(dd_space_key_strings[DD_SPACE_ID])) { |
| 20277 | ✗ | my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name); | |
| 20278 | ✗ | return (DD_FAILURE); | |
| 20279 | } | ||
| 20280 | |||
| 20281 | space_id_t space_id; | ||
| 20282 | |||
| 20283 |
2/4✓ Branch 0 taken 251509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251509 times.
✗ Branch 3 not taken.
|
251509 | ts_se_private_data.get(dd_space_key_strings[DD_SPACE_ID], &space_id); |
| 20284 | |||
| 20285 |
3/4✓ Branch 0 taken 251509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50486 times.
✓ Branch 3 taken 201023 times.
|
251509 | if (fsp_is_undo_tablespace(space_id)) { |
| 20286 | /* Get the ddl_mutex so that if an undo truncation is happening by | ||
| 20287 | the purge thread, it will complete before we continue. */ | ||
| 20288 |
1/2✓ Branch 0 taken 50486 times.
✗ Branch 1 not taken.
|
50486 | mutex_enter(&undo::ddl_mutex); |
| 20289 | |||
| 20290 | /* When selecting information_schema.files, no MVCC is used. So it is | ||
| 20291 | possible to read an uncommitted DD record that indicates the undo | ||
| 20292 | space is empty and shows the new space_id after a truncation. | ||
| 20293 | Adjust for that possibility by always using the current space_id. */ | ||
| 20294 |
1/2✓ Branch 0 taken 50486 times.
✗ Branch 1 not taken.
|
50486 | undo::spaces->s_lock(); |
| 20295 | 50486 | space_id_t undo_num = undo::id2num(space_id); | |
| 20296 |
1/2✓ Branch 0 taken 50486 times.
✗ Branch 1 not taken.
|
50486 | undo::Tablespace *undo_space = undo::spaces->find(undo_num); |
| 20297 |
2/2✓ Branch 0 taken 50479 times.
✓ Branch 1 taken 7 times.
|
50486 | if (undo_space != nullptr) { |
| 20298 | 50479 | space_id = undo_space->id(); | |
| 20299 | } | ||
| 20300 |
1/2✓ Branch 0 taken 50486 times.
✗ Branch 1 not taken.
|
50486 | undo::spaces->s_unlock(); |
| 20301 | } | ||
| 20302 | |||
| 20303 |
1/2✓ Branch 0 taken 251509 times.
✗ Branch 1 not taken.
|
251509 | auto space = fil_space_acquire(space_id); |
| 20304 | |||
| 20305 | /* Tablespace is missing in this case. */ | ||
| 20306 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 251470 times.
|
251509 | if (space == nullptr) { |
| 20307 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name); |
| 20308 |
3/4✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 32 times.
|
39 | if (fsp_is_undo_tablespace(space_id)) { |
| 20309 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | mutex_exit(&undo::ddl_mutex); |
| 20310 | } | ||
| 20311 | 39 | return (DD_FAILURE); | |
| 20312 | } | ||
| 20313 | |||
| 20314 | 251470 | stats->m_id = space->id; | |
| 20315 | |||
| 20316 | 251470 | const char *type = "TABLESPACE"; | |
| 20317 | |||
| 20318 | 251470 | fil_type_t purpose = space->purpose; | |
| 20319 | |||
| 20320 |
2/4✓ Branch 0 taken 226499 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24971 times.
✗ Branch 3 not taken.
|
251470 | switch (purpose) { |
| 20321 | 226499 | case FIL_TYPE_TABLESPACE: | |
| 20322 |
3/4✓ Branch 0 taken 226499 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50479 times.
✓ Branch 3 taken 176020 times.
|
226499 | if (fsp_is_undo_tablespace(space_id)) { |
| 20323 | 50479 | type = "UNDO LOG"; | |
| 20324 | 50479 | break; | |
| 20325 | } /* else fall through for TABLESPACE */ | ||
| 20326 | case FIL_TYPE_IMPORT: | ||
| 20327 | /* 'IMPORTING'is a status. The type is TABLESPACE. */ | ||
| 20328 | 176020 | break; | |
| 20329 | 24971 | case FIL_TYPE_TEMPORARY: | |
| 20330 | 24971 | type = "TEMPORARY"; | |
| 20331 | 24971 | break; | |
| 20332 | } | ||
| 20333 | |||
| 20334 |
1/2✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
|
251470 | stats->m_type = type; |
| 20335 | |||
| 20336 | 251470 | stats->m_free_extents = space->free_len; | |
| 20337 | |||
| 20338 |
1/2✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
|
251470 | page_size_t page_size{space->flags}; |
| 20339 | |||
| 20340 |
1/2✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
|
251470 | page_no_t extent_pages = fsp_get_extent_size_in_pages(page_size); |
| 20341 | |||
| 20342 | 251470 | stats->m_total_extents = space->size_in_header / extent_pages; | |
| 20343 | |||
| 20344 |
1/2✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
|
251470 | stats->m_extent_size = extent_pages * page_size.physical(); |
| 20345 | |||
| 20346 | 251470 | const fil_node_t *file = nullptr; | |
| 20347 | |||
| 20348 | /* Use only the basename when searching for system tablespaces since | ||
| 20349 | InnoDB places them in innodb_data_home_dir and the DD may only know | ||
| 20350 | the basename. Since they are open, they are in the right place. */ | ||
| 20351 | std::string search_name = | ||
| 20352 |
2/2✓ Branch 0 taken 24971 times.
✓ Branch 1 taken 201515 times.
|
226486 | (space->id == TRX_SYS_SPACE || space->id == dict_sys_t::s_temp_space_id) |
| 20353 | 251470 | ? Fil_path::get_basename(file_name) | |
| 20354 |
11/20✓ Branch 0 taken 226486 times.
✓ Branch 1 taken 24984 times.
✓ Branch 2 taken 49955 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 49955 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 201515 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 201515 times.
✓ Branch 9 taken 49955 times.
✓ Branch 10 taken 49955 times.
✓ Branch 11 taken 201515 times.
✓ Branch 12 taken 49955 times.
✓ Branch 13 taken 201515 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
1030851 | : file_name; |
| 20355 | |||
| 20356 | /* Normalize the file name to search for. */ | ||
| 20357 | 251470 | Fil_path::normalize(search_name); | |
| 20358 | |||
| 20359 | /* Find the fil_node_t that matches the filename. */ | ||
| 20360 |
1/2✓ Branch 0 taken 251487 times.
✗ Branch 1 not taken.
|
251487 | for (const auto &f : space->files) { |
| 20361 |
4/6✓ Branch 0 taken 251487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251487 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 251463 times.
✓ Branch 5 taken 24 times.
|
251487 | if (Fil_path::is_same_as(search_name, f.name)) { |
| 20362 | 251463 | file = &f; | |
| 20363 | 251463 | break; | |
| 20364 | } | ||
| 20365 | |||
| 20366 | /* Try to compare only the basename. */ | ||
| 20367 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 21 times.
|
24 | if (space->id == TRX_SYS_SPACE || |
| 20368 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | space->id == dict_sys_t::s_temp_space_id) { |
| 20369 |
5/8✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 17 times.
|
24 | if (Fil_path::is_same_as(search_name, Fil_path::get_basename(f.name))) { |
| 20370 | 7 | file = &f; | |
| 20371 | 7 | break; | |
| 20372 | } | ||
| 20373 | } | ||
| 20374 | |||
| 20375 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (space->files.size() == 1) { |
| 20376 | ✗ | file = &f; | |
| 20377 | |||
| 20378 | ✗ | ib::info(ER_IB_MSG_570) | |
| 20379 | ✗ | << "Tablespace '" << tablespace_name << "'with DD filename '" | |
| 20380 | ✗ | << file_name << "' doesn't match the InnoDB filename '" << f.name | |
| 20381 | ✗ | << "'"; | |
| 20382 | } | ||
| 20383 | } | ||
| 20384 | |||
| 20385 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 251470 times.
|
251470 | if (file == nullptr) { |
| 20386 | ✗ | ib::warn(ER_IB_MSG_571) << "Tablespace '" << tablespace_name << "'" | |
| 20387 | ✗ | << " filename is unknown. Use --innodb-directories" | |
| 20388 | ✗ | << " to tell InnoDB the location of the file."; | |
| 20389 | |||
| 20390 | ✗ | my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name); | |
| 20391 | |||
| 20392 | ✗ | if (fsp_is_undo_tablespace(space_id)) { | |
| 20393 | ✗ | mutex_exit(&undo::ddl_mutex); | |
| 20394 | } | ||
| 20395 | |||
| 20396 | ✗ | return (DD_FAILURE); | |
| 20397 | } | ||
| 20398 | |||
| 20399 |
1/2✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
|
251470 | stats->m_initial_size = file->init_size * page_size.physical(); |
| 20400 | |||
| 20401 | /** Store maximum size */ | ||
| 20402 |
2/2✓ Branch 0 taken 251457 times.
✓ Branch 1 taken 13 times.
|
251470 | if (file->max_size >= PAGE_NO_MAX) { |
| 20403 | 251457 | stats->m_maximum_size = ~0ULL; | |
| 20404 | } else { | ||
| 20405 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | stats->m_maximum_size = file->max_size * page_size.physical(); |
| 20406 | } | ||
| 20407 | |||
| 20408 | /** Store autoextend size */ | ||
| 20409 | page_no_t extend_pages; | ||
| 20410 | |||
| 20411 |
2/2✓ Branch 0 taken 24984 times.
✓ Branch 1 taken 226486 times.
|
251470 | if (space->id == TRX_SYS_SPACE) { |
| 20412 |
1/2✓ Branch 0 taken 24984 times.
✗ Branch 1 not taken.
|
24984 | extend_pages = srv_sys_space.get_increment(); |
| 20413 | |||
| 20414 |
3/4✓ Branch 0 taken 226486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24971 times.
✓ Branch 3 taken 201515 times.
|
226486 | } else if (fsp_is_system_temporary(space->id)) { |
| 20415 |
1/2✓ Branch 0 taken 24971 times.
✗ Branch 1 not taken.
|
24971 | extend_pages = srv_tmp_space.get_increment(); |
| 20416 | |||
| 20417 |
3/4✓ Branch 0 taken 201515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50479 times.
✓ Branch 3 taken 151036 times.
|
201515 | } else if (fsp_is_undo_tablespace(space->id)) { |
| 20418 | 50479 | extend_pages = space->m_undo_extend; | |
| 20419 | |||
| 20420 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 151036 times.
|
151036 | } else if (space->autoextend_size_in_bytes > 0) { |
| 20421 | ✗ | extend_pages = space->autoextend_size_in_bytes / page_size.physical(); | |
| 20422 | } else { | ||
| 20423 |
1/2✓ Branch 0 taken 151036 times.
✗ Branch 1 not taken.
|
151036 | extend_pages = fsp_get_pages_to_extend_ibd(page_size, file->size); |
| 20424 | } | ||
| 20425 | |||
| 20426 |
1/2✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
|
251470 | stats->m_autoextend_size = extend_pages * page_size.physical(); |
| 20427 | |||
| 20428 |
1/2✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
|
251470 | auto avail_space = fsp_get_available_space_in_free_extents(space); |
| 20429 | |||
| 20430 | 251470 | stats->m_data_free = avail_space * 1024; | |
| 20431 | |||
| 20432 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 251470 times.
✓ Branch 2 taken 251470 times.
✗ Branch 3 not taken.
|
251470 | stats->m_status = (purpose == FIL_TYPE_IMPORT ? "IMPORTING" : "NORMAL"); |
| 20433 | |||
| 20434 |
1/2✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
|
251470 | fil_space_release(space); |
| 20435 | |||
| 20436 |
3/4✓ Branch 0 taken 251470 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50479 times.
✓ Branch 3 taken 200991 times.
|
251470 | if (fsp_is_undo_tablespace(space_id)) { |
| 20437 |
1/2✓ Branch 0 taken 50479 times.
✗ Branch 1 not taken.
|
50479 | mutex_exit(&undo::ddl_mutex); |
| 20438 | } | ||
| 20439 | |||
| 20440 | 251470 | return (DD_SUCCESS); | |
| 20441 | } | ||
| 20442 | |||
| 20443 | /** Enable indexes. | ||
| 20444 | @param[in] mode enable index mode. | ||
| 20445 | @return HA_ERR_* error code or 0 */ | ||
| 20446 | 525 | int ha_innobase::enable_indexes(uint mode) { | |
| 20447 | 525 | int error = HA_ERR_WRONG_COMMAND; | |
| 20448 | |||
| 20449 | /* Enable index only for intrinsic table. Behavior for all other | ||
| 20450 | table continue to remain same. */ | ||
| 20451 | |||
| 20452 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 525 times.
|
525 | if (m_prebuilt->table->is_intrinsic()) { |
| 20453 | ✗ | ut_ad(mode == HA_KEY_SWITCH_ALL); | |
| 20454 | ✗ | for (auto index : m_prebuilt->table->indexes) { | |
| 20455 | /* InnoDB being clustered index we can't disable/enable | ||
| 20456 | clustered index itself. */ | ||
| 20457 | ✗ | if (index->is_clustered()) { | |
| 20458 | ✗ | continue; | |
| 20459 | } | ||
| 20460 | |||
| 20461 | ✗ | index->allow_duplicates = false; | |
| 20462 | } | ||
| 20463 | ✗ | error = 0; | |
| 20464 | } | ||
| 20465 | |||
| 20466 | 525 | return (error); | |
| 20467 | } | ||
| 20468 | |||
| 20469 | /** Disable indexes. | ||
| 20470 | @param[in] mode disable index mode. | ||
| 20471 | @return HA_ERR_* error code or 0 */ | ||
| 20472 | 546 | int ha_innobase::disable_indexes(uint mode) { | |
| 20473 | 546 | int error = HA_ERR_WRONG_COMMAND; | |
| 20474 | |||
| 20475 | /* Disable index only for intrinsic table. Behavior for all other | ||
| 20476 | table continue to remain same. */ | ||
| 20477 | |||
| 20478 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 546 times.
|
546 | if (m_prebuilt->table->is_intrinsic()) { |
| 20479 | ✗ | ut_ad(mode == HA_KEY_SWITCH_ALL); | |
| 20480 | ✗ | for (auto index : m_prebuilt->table->indexes) { | |
| 20481 | /* InnoDB being clustered index we can't disable/enable | ||
| 20482 | clustered index itself. */ | ||
| 20483 | ✗ | if (index->is_clustered()) { | |
| 20484 | ✗ | continue; | |
| 20485 | } | ||
| 20486 | |||
| 20487 | ✗ | index->allow_duplicates = true; | |
| 20488 | } | ||
| 20489 | ✗ | error = 0; | |
| 20490 | } | ||
| 20491 | |||
| 20492 | 546 | return (error); | |
| 20493 | } | ||
| 20494 | |||
| 20495 | /** | ||
| 20496 | Updates index cardinalities of the table, based on random dives into | ||
| 20497 | each index tree. This does NOT calculate exact statistics on the table. | ||
| 20498 | @return HA_ADMIN_* error code or HA_ADMIN_OK */ | ||
| 20499 | |||
| 20500 | 13806 | int ha_innobase::analyze(THD *, /*!< in: connection thread handle */ | |
| 20501 | HA_CHECK_OPT *) /*!< in: currently ignored */ | ||
| 20502 | { | ||
| 20503 |
5/10✓ Branch 0 taken 12373 times.
✓ Branch 1 taken 1433 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12373 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 13806 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 13806 times.
|
13806 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 20504 | m_share->ib_table->is_corrupt)) { | ||
| 20505 | ✗ | return (HA_ADMIN_CORRUPT); | |
| 20506 | } | ||
| 20507 | |||
| 20508 | /* Simply call info_low() with all the flags | ||
| 20509 | and request recalculation of the statistics */ | ||
| 20510 | 13806 | int ret = info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE, | |
| 20511 | true /* this is ANALYZE */); | ||
| 20512 | |||
| 20513 |
5/10✓ Branch 0 taken 12373 times.
✓ Branch 1 taken 1433 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12373 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 13806 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 13806 times.
|
13806 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 20514 | m_share->ib_table->is_corrupt)) { | ||
| 20515 | ✗ | return (HA_ADMIN_CORRUPT); | |
| 20516 | } | ||
| 20517 | |||
| 20518 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 13801 times.
|
13806 | if (ret != 0) { |
| 20519 | 5 | return (HA_ADMIN_FAILED); | |
| 20520 | } | ||
| 20521 | |||
| 20522 | 13801 | return (HA_ADMIN_OK); | |
| 20523 | } | ||
| 20524 | |||
| 20525 | /** This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds | ||
| 20526 | the table in MySQL. */ | ||
| 20527 | |||
| 20528 | 2078 | int ha_innobase::optimize(THD *, /*!< in: connection thread handle */ | |
| 20529 | HA_CHECK_OPT *) /*!< in: currently ignored */ | ||
| 20530 | { | ||
| 20531 |
1/2✓ Branch 0 taken 2078 times.
✗ Branch 1 not taken.
|
2078 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 20532 | |||
| 20533 | /* FTS-FIXME: Since MySQL doesn't support engine-specific commands, | ||
| 20534 | we have to hijack some existing command in order to be able to test | ||
| 20535 | the new admin commands added in InnoDB's FTS support. For now, we | ||
| 20536 | use MySQL's OPTIMIZE command, normally mapped to ALTER TABLE in | ||
| 20537 | InnoDB (so it recreates the table anew), and map it to OPTIMIZE. | ||
| 20538 | |||
| 20539 | This works OK otherwise, but MySQL locks the entire table during | ||
| 20540 | calls to OPTIMIZE, which is undesirable. */ | ||
| 20541 | |||
| 20542 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2071 times.
|
2078 | if (innodb_optimize_fulltext_only) { |
| 20543 |
3/6✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
14 | if (m_prebuilt->table->fts && m_prebuilt->table->fts->cache && |
| 20544 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | !dict_table_is_discarded(m_prebuilt->table)) { |
| 20545 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | fts_sync_table(m_prebuilt->table, false, true, false); |
| 20546 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | fts_optimize_table(m_prebuilt->table); |
| 20547 | } | ||
| 20548 | 7 | return (HA_ADMIN_OK); | |
| 20549 | } else { | ||
| 20550 | 2071 | return (HA_ADMIN_TRY_ALTER); | |
| 20551 | } | ||
| 20552 | 2078 | } | |
| 20553 | |||
| 20554 | /** Tries to check that an InnoDB table is not corrupted. If corruption is | ||
| 20555 | noticed, prints to stderr information about it. In case of corruption | ||
| 20556 | may also assert a failure and crash the server. | ||
| 20557 | @return HA_ADMIN_CORRUPT or HA_ADMIN_OK */ | ||
| 20558 | |||
| 20559 | 7593 | int ha_innobase::check(THD *thd, /*!< in: user thread handle */ | |
| 20560 | HA_CHECK_OPT *check_opt) /*!< in: check options */ | ||
| 20561 | { | ||
| 20562 | dict_index_t *index; | ||
| 20563 | ulint n_rows; | ||
| 20564 | 7593 | ulint n_rows_in_table = ULINT_UNDEFINED; | |
| 20565 | 7593 | ulint n_dups = 0; | |
| 20566 | 7593 | bool is_ok = true; | |
| 20567 | ulint old_isolation_level; | ||
| 20568 | dberr_t ret; | ||
| 20569 | |||
| 20570 |
1/2✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
|
7593 | DBUG_TRACE; |
| 20571 |
2/4✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7593 times.
|
7593 | assert(thd == ha_thd()); |
| 20572 | #ifdef WITH_WSREP | ||
| 20573 |
2/4✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7593 times.
✗ Branch 3 not taken.
|
7593 | DEBUG_SYNC(thd, "ha_innobase_check"); |
| 20574 | #endif /* WITH_WSREP */ | ||
| 20575 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7593 times.
|
7593 | ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 20576 |
2/4✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7593 times.
|
7593 | ut_a(m_prebuilt->trx == thd_to_trx(thd)); |
| 20577 | |||
| 20578 |
1/2✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
|
7593 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 20579 | |||
| 20580 |
2/2✓ Branch 0 taken 1324 times.
✓ Branch 1 taken 6269 times.
|
7593 | if (m_prebuilt->mysql_template == nullptr) { |
| 20581 | /* Build the template; we will use a dummy template | ||
| 20582 | in index scans done in checking */ | ||
| 20583 | |||
| 20584 |
1/2✓ Branch 0 taken 1324 times.
✗ Branch 1 not taken.
|
1324 | build_template(true); |
| 20585 | } | ||
| 20586 | |||
| 20587 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7589 times.
|
7593 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 20588 | 4 | ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, | |
| 20589 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | table->s->table_name.str); |
| 20590 | |||
| 20591 | 4 | return HA_ADMIN_CORRUPT; | |
| 20592 | |||
| 20593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7589 times.
|
7589 | } else if (m_prebuilt->table->ibd_file_missing) { |
| 20594 | ✗ | ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING, | |
| 20595 | ✗ | table->s->table_name.str); | |
| 20596 | |||
| 20597 | ✗ | return HA_ADMIN_CORRUPT; | |
| 20598 | } | ||
| 20599 | |||
| 20600 | 7589 | m_prebuilt->trx->op_info = "checking table"; | |
| 20601 | |||
| 20602 |
2/4✓ Branch 0 taken 7589 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7589 times.
|
7589 | if (m_prebuilt->table->is_corrupted()) { |
| 20603 | /* Now that the table is already marked as corrupted, | ||
| 20604 | there is no need to check any index of this table */ | ||
| 20605 | ✗ | m_prebuilt->trx->op_info = ""; | |
| 20606 | ✗ | if (thd_killed(m_user_thd)) { | |
| 20607 | ✗ | thd_set_kill_status(m_user_thd); | |
| 20608 | } | ||
| 20609 | |||
| 20610 | ✗ | return HA_ADMIN_CORRUPT; | |
| 20611 | } | ||
| 20612 | |||
| 20613 | 7589 | old_isolation_level = m_prebuilt->trx->isolation_level; | |
| 20614 | |||
| 20615 | /* We must run the index record counts at an isolation level | ||
| 20616 | >= READ COMMITTED, because a dirty read can see a wrong number | ||
| 20617 | of records in some index; to play safe, we use always | ||
| 20618 | REPEATABLE READ here */ | ||
| 20619 | 7589 | m_prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ; | |
| 20620 | |||
| 20621 |
2/4✓ Branch 0 taken 7589 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7589 times.
|
7589 | ut_ad(!m_prebuilt->table->is_corrupted()); |
| 20622 | |||
| 20623 |
3/4✓ Branch 0 taken 7589 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11198 times.
✓ Branch 3 taken 7584 times.
|
18782 | for (index = m_prebuilt->table->first_index(); index != nullptr; |
| 20624 |
1/2✓ Branch 0 taken 11193 times.
✗ Branch 1 not taken.
|
11193 | index = index->next()) { |
| 20625 | /* If this is an index being created or dropped, skip */ | ||
| 20626 |
3/4✓ Branch 0 taken 11198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 11196 times.
|
11198 | if (!index->is_committed()) { |
| 20627 | 2 | continue; | |
| 20628 | } | ||
| 20629 | |||
| 20630 |
6/8✓ Branch 0 taken 11196 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11196 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11179 times.
✓ Branch 5 taken 17 times.
✓ Branch 6 taken 11179 times.
✓ Branch 7 taken 17 times.
|
11196 | if (!(check_opt->flags & T_QUICK) && !index->is_corrupted()) { |
| 20631 | /* Enlarge the fatal lock wait timeout during | ||
| 20632 | CHECK TABLE. */ | ||
| 20633 | srv_fatal_semaphore_wait_extend.fetch_add(1); | ||
| 20634 | |||
| 20635 |
1/2✓ Branch 0 taken 11179 times.
✗ Branch 1 not taken.
|
11179 | bool valid = btr_validate_index(index, m_prebuilt->trx, false); |
| 20636 | |||
| 20637 | /* Restore the fatal lock wait timeout after | ||
| 20638 | CHECK TABLE. */ | ||
| 20639 | srv_fatal_semaphore_wait_extend.fetch_sub(1); | ||
| 20640 | |||
| 20641 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11179 times.
|
11179 | if (!valid) { |
| 20642 | ✗ | is_ok = false; | |
| 20643 | |||
| 20644 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE, | |
| 20645 | "InnoDB: The B-tree of" | ||
| 20646 | " index %s is corrupted.", | ||
| 20647 | index->name()); | ||
| 20648 | ✗ | continue; | |
| 20649 | } | ||
| 20650 | } | ||
| 20651 | |||
| 20652 | /* Instead of invoking change_active_index(), set up | ||
| 20653 | a dummy template for non-locking reads, disabling | ||
| 20654 | access to the clustered index. */ | ||
| 20655 | 11196 | m_prebuilt->index = index; | |
| 20656 | |||
| 20657 |
1/2✓ Branch 0 taken 11196 times.
✗ Branch 1 not taken.
|
11196 | m_prebuilt->index_usable = m_prebuilt->index->is_usable(m_prebuilt->trx); |
| 20658 | |||
| 20659 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 11179 times.
|
11196 | if (!m_prebuilt->index_usable) { |
| 20660 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | if (m_prebuilt->index->is_corrupted()) { |
| 20661 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | push_warning_printf(m_user_thd, Sql_condition::SL_WARNING, |
| 20662 | HA_ERR_INDEX_CORRUPT, | ||
| 20663 | "InnoDB: Index %s is marked as" | ||
| 20664 | " corrupted", | ||
| 20665 | index->name()); | ||
| 20666 | 17 | is_ok = false; | |
| 20667 | } else { | ||
| 20668 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, | |
| 20669 | HA_ERR_TABLE_DEF_CHANGED, | ||
| 20670 | "InnoDB: Insufficient history for" | ||
| 20671 | " index %s", | ||
| 20672 | index->name()); | ||
| 20673 | } | ||
| 20674 | 17 | continue; | |
| 20675 | } | ||
| 20676 | |||
| 20677 | 11179 | m_prebuilt->sql_stat_start = true; | |
| 20678 | 11179 | m_prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE; | |
| 20679 | 11179 | m_prebuilt->n_template = 0; | |
| 20680 | 11179 | m_prebuilt->need_to_access_clustered = false; | |
| 20681 | |||
| 20682 |
1/2✓ Branch 0 taken 11179 times.
✗ Branch 1 not taken.
|
11179 | m_prebuilt->clear_search_tuples(); |
| 20683 | |||
| 20684 | 11179 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 20685 | |||
| 20686 |
1/2✓ Branch 0 taken 11179 times.
✗ Branch 1 not taken.
|
11179 | size_t max_threads = thd_parallel_read_threads(m_prebuilt->trx->mysql_thd); |
| 20687 | |||
| 20688 | /* Scan this index. */ | ||
| 20689 |
3/4✓ Branch 0 taken 11179 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 11110 times.
|
11179 | if (dict_index_is_spatial(index)) { |
| 20690 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | ret = row_count_rtree_recs(m_prebuilt, &n_rows, &n_dups); |
| 20691 | } else { | ||
| 20692 |
1/2✓ Branch 0 taken 11109 times.
✗ Branch 1 not taken.
|
11110 | ret = row_scan_index_for_mysql(m_prebuilt, index, max_threads, true, |
| 20693 | &n_rows); | ||
| 20694 | } | ||
| 20695 | |||
| 20696 |
5/8✓ Branch 0 taken 11178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 11176 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
11178 | DBUG_EXECUTE_IF( |
| 20697 | "dict_set_clust_index_corrupted", | ||
| 20698 | if (index->is_clustered()) { ret = DB_CORRUPTION; }); | ||
| 20699 | |||
| 20700 |
6/8✓ Branch 0 taken 11178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 11161 times.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 6 times.
|
11178 | DBUG_EXECUTE_IF( |
| 20701 | "dict_set_index_corrupted", | ||
| 20702 | if (!index->is_clustered()) { ret = DB_CORRUPTION; }); | ||
| 20703 | |||
| 20704 |
6/8✓ Branch 0 taken 11178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11178 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 11176 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 11176 times.
|
11178 | if (ret == DB_INTERRUPTED || thd_killed(m_user_thd)) { |
| 20705 | /* Do not report error since this could happen | ||
| 20706 | during shutdown */ | ||
| 20707 | 2 | break; | |
| 20708 | } | ||
| 20709 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 11163 times.
|
11176 | if (ret != DB_SUCCESS) { |
| 20710 | /* Assume some kind of corruption. */ | ||
| 20711 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE, |
| 20712 | "InnoDB: The B-tree of" | ||
| 20713 | " index %s is corrupted.", | ||
| 20714 | index->name()); | ||
| 20715 | 13 | is_ok = false; | |
| 20716 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
13 | dict_set_corrupted(index); |
| 20717 | } | ||
| 20718 | |||
| 20719 |
3/4✓ Branch 0 taken 11174 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7586 times.
✓ Branch 3 taken 3588 times.
|
11174 | if (index == m_prebuilt->table->first_index()) { |
| 20720 | 7586 | n_rows_in_table = n_rows; | |
| 20721 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 3501 times.
|
3542 | } else if (!(index->type & DICT_FTS) && (n_rows != n_rows_in_table) && |
| 20722 |
5/8✓ Branch 0 taken 3542 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 41 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3588 times.
|
7130 | (!index->is_multi_value()) && |
| 20723 | ✗ | (!dict_index_is_spatial(index) || (n_rows < n_rows_in_table) || | |
| 20724 | ✗ | (n_dups < n_rows - n_rows_in_table))) { | |
| 20725 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE, | |
| 20726 | "InnoDB: Index '%-.200s' contains %lu" | ||
| 20727 | " entries, should be %lu.", | ||
| 20728 | index->name(), (ulong)n_rows, (ulong)n_rows_in_table); | ||
| 20729 | ✗ | is_ok = false; | |
| 20730 | ✗ | dict_set_corrupted(index); | |
| 20731 | } | ||
| 20732 | } | ||
| 20733 | |||
| 20734 | /* Restore the original isolation level */ | ||
| 20735 | 7586 | m_prebuilt->trx->isolation_level = | |
| 20736 | 7586 | static_cast<trx_t::isolation_level_t>(old_isolation_level); | |
| 20737 | |||
| 20738 | #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG | ||
| 20739 | /* We validate the whole adaptive hash index for all tables | ||
| 20740 | at every CHECK TABLE only when QUICK flag is not present. */ | ||
| 20741 | |||
| 20742 |
4/8✓ Branch 0 taken 7586 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7586 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7586 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7586 times.
|
7586 | if (!(check_opt->flags & T_QUICK) && !btr_search_validate()) { |
| 20743 | ✗ | push_warning(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE, | |
| 20744 | "InnoDB: The adaptive hash index is corrupted."); | ||
| 20745 | ✗ | is_ok = false; | |
| 20746 | } | ||
| 20747 | #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ | ||
| 20748 | 7586 | m_prebuilt->trx->op_info = ""; | |
| 20749 |
3/4✓ Branch 0 taken 7586 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7584 times.
|
7586 | if (thd_killed(m_user_thd)) { |
| 20750 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | thd_set_kill_status(m_user_thd); |
| 20751 | } | ||
| 20752 | |||
| 20753 |
5/10✓ Branch 0 taken 1167 times.
✓ Branch 1 taken 6419 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1167 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7586 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 7586 times.
|
7586 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 20754 | m_share->ib_table->is_corrupt)) { | ||
| 20755 | ✗ | return HA_ADMIN_CORRUPT; | |
| 20756 | } | ||
| 20757 | |||
| 20758 |
2/2✓ Branch 0 taken 7570 times.
✓ Branch 1 taken 16 times.
|
7586 | return is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT; |
| 20759 | 7590 | } | |
| 20760 | |||
| 20761 | /** Tells something additional to the handler about how to do things. | ||
| 20762 | @return 0 or error number */ | ||
| 20763 | |||
| 20764 | 945534733 | int ha_innobase::extra(enum ha_extra_function operation) | |
| 20765 | /*!< in: HA_EXTRA_FLUSH or some other flag */ | ||
| 20766 | { | ||
| 20767 |
1/2✓ Branch 0 taken 945538185 times.
✗ Branch 1 not taken.
|
945534733 | if (m_prebuilt->table) { |
| 20768 | #ifdef UNIV_DEBUG | ||
| 20769 |
1/2✓ Branch 0 taken 945536303 times.
✗ Branch 1 not taken.
|
945538185 | if (m_prebuilt->table->n_ref_count > 0) |
| 20770 | #endif /* UNIV_DEBUG */ | ||
| 20771 | 945536303 | update_thd(); | |
| 20772 | } | ||
| 20773 | |||
| 20774 | /* Warning: since it is not sure that MySQL calls external_lock | ||
| 20775 | before calling this function, the trx field in m_prebuilt can be | ||
| 20776 | obsolete! */ | ||
| 20777 | |||
| 20778 |
13/14✗ Branch 0 not taken.
✓ Branch 1 taken 101599777 times.
✓ Branch 2 taken 1400803 times.
✓ Branch 3 taken 1431304 times.
✓ Branch 4 taken 198970 times.
✓ Branch 5 taken 74216 times.
✓ Branch 6 taken 107336430 times.
✓ Branch 7 taken 1958984 times.
✓ Branch 8 taken 107336988 times.
✓ Branch 9 taken 2390110 times.
✓ Branch 10 taken 8321 times.
✓ Branch 11 taken 8319 times.
✓ Branch 12 taken 90827755 times.
✓ Branch 13 taken 530963940 times.
|
945535917 | switch (operation) { |
| 20779 | ✗ | case HA_EXTRA_FLUSH: | |
| 20780 | ✗ | if (m_prebuilt->blob_heap) { | |
| 20781 | ✗ | row_mysql_prebuilt_free_blob_heap(m_prebuilt); | |
| 20782 | } | ||
| 20783 | |||
| 20784 | ✗ | if (m_prebuilt->compress_heap) { | |
| 20785 | ✗ | row_mysql_prebuilt_free_compress_heap(m_prebuilt); | |
| 20786 | } | ||
| 20787 | |||
| 20788 | ✗ | break; | |
| 20789 | 101599777 | case HA_EXTRA_RESET_STATE: | |
| 20790 | 101599777 | reset_template(); | |
| 20791 | 101599771 | m_prebuilt->replace = 0; | |
| 20792 | 101599771 | m_prebuilt->on_duplicate_key_update = 0; | |
| 20793 | 101599771 | break; | |
| 20794 | 1400803 | case HA_EXTRA_NO_KEYREAD: | |
| 20795 | 1400803 | m_prebuilt->read_just_key = 0; | |
| 20796 | 1400803 | break; | |
| 20797 | 1431304 | case HA_EXTRA_KEYREAD: | |
| 20798 | 1431304 | m_prebuilt->read_just_key = 1; | |
| 20799 | 1431304 | break; | |
| 20800 | 198970 | case HA_EXTRA_KEYREAD_PRESERVE_FIELDS: | |
| 20801 | 198970 | m_prebuilt->keep_other_fields_on_keyread = 1; | |
| 20802 | 198970 | break; | |
| 20803 | |||
| 20804 | /* IMPORTANT: m_prebuilt->trx can be obsolete in | ||
| 20805 | this method, because it is not sure that MySQL | ||
| 20806 | calls external_lock before this method with the | ||
| 20807 | parameters below. We must not invoke update_thd() | ||
| 20808 | either, because the calling threads may change. | ||
| 20809 | CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */ | ||
| 20810 | 74216 | case HA_EXTRA_INSERT_WITH_UPDATE: | |
| 20811 | 74216 | m_prebuilt->on_duplicate_key_update = 1; | |
| 20812 | 74216 | break; | |
| 20813 | 107336430 | case HA_EXTRA_NO_IGNORE_DUP_KEY: | |
| 20814 | 107336430 | m_prebuilt->on_duplicate_key_update = 0; | |
| 20815 | 107336430 | break; | |
| 20816 | 1958984 | case HA_EXTRA_WRITE_CAN_REPLACE: | |
| 20817 | 1958984 | m_prebuilt->replace = 1; | |
| 20818 | 1958984 | break; | |
| 20819 | 107336988 | case HA_EXTRA_WRITE_CANNOT_REPLACE: | |
| 20820 | 107336988 | m_prebuilt->replace = 0; | |
| 20821 | 107336988 | break; | |
| 20822 | 2390110 | case HA_EXTRA_NO_READ_LOCKING: | |
| 20823 | 2390110 | m_prebuilt->no_read_locking = true; | |
| 20824 | 2390110 | break; | |
| 20825 | 8321 | case HA_EXTRA_BEGIN_ALTER_COPY: | |
| 20826 | 8321 | m_prebuilt->table->skip_alter_undo = 1; | |
| 20827 | 8321 | break; | |
| 20828 | 8319 | case HA_EXTRA_END_ALTER_COPY: | |
| 20829 | 8319 | m_prebuilt->table->skip_alter_undo = 0; | |
| 20830 | 8319 | break; | |
| 20831 | 90827755 | case HA_EXTRA_NO_AUTOINC_LOCKING: | |
| 20832 | 90827755 | m_prebuilt->no_autoinc_locking = true; | |
| 20833 | 90827755 | break; | |
| 20834 | 945535911 | default: /* Do nothing */ | |
| 20835 | ; | ||
| 20836 | } | ||
| 20837 | |||
| 20838 | 945535911 | return (0); | |
| 20839 | } | ||
| 20840 | |||
| 20841 | /** | ||
| 20842 | MySQL calls this method at the end of each statement. This method | ||
| 20843 | exists for readability only. ha_innobase::reset() doesn't give any | ||
| 20844 | clue about the method. */ | ||
| 20845 | |||
| 20846 | 107334995 | int ha_innobase::end_stmt() { | |
| 20847 |
2/2✓ Branch 0 taken 11922294 times.
✓ Branch 1 taken 95412701 times.
|
107334995 | if (m_prebuilt->blob_heap) { |
| 20848 | 11922294 | row_mysql_prebuilt_free_blob_heap(m_prebuilt); | |
| 20849 | } | ||
| 20850 | |||
| 20851 |
2/2✓ Branch 0 taken 16633 times.
✓ Branch 1 taken 107318521 times.
|
107335154 | if (m_prebuilt->compress_heap) { |
| 20852 | 16633 | row_mysql_prebuilt_free_compress_heap(m_prebuilt); | |
| 20853 | } | ||
| 20854 | |||
| 20855 | 107335154 | m_prebuilt->end_stmt(); | |
| 20856 | |||
| 20857 | 107335832 | reset_template(); | |
| 20858 | |||
| 20859 | 107336499 | m_ds_mrr.reset(); | |
| 20860 | |||
| 20861 | /* TODO: This should really be reset in reset_template() but for now | ||
| 20862 | it's safer to do it explicitly here. */ | ||
| 20863 | |||
| 20864 | /* This is a statement level counter. */ | ||
| 20865 | 107336725 | m_prebuilt->autoinc_last_value = 0; | |
| 20866 | |||
| 20867 | 107336725 | m_prebuilt->no_read_locking = false; | |
| 20868 | 107336725 | m_prebuilt->no_autoinc_locking = false; | |
| 20869 | |||
| 20870 | /* This transaction had called ha_innobase::start_stmt() */ | ||
| 20871 | 107336725 | trx_t *trx = m_prebuilt->trx; | |
| 20872 | |||
| 20873 |
4/6✓ Branch 0 taken 107100456 times.
✓ Branch 1 taken 236372 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 107100688 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 107337060 times.
|
107336725 | if (!m_prebuilt->table->is_temporary() && trx != thd_to_trx(ha_thd())) { |
| 20874 | ✗ | ut_d(ut_error); | |
| 20875 | ut_o(return (0)); | ||
| 20876 | } | ||
| 20877 | |||
| 20878 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 107336902 times.
|
107337060 | ut_ad(!m_prebuilt->replace); |
| 20879 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 107336838 times.
|
107336902 | ut_ad(!m_prebuilt->on_duplicate_key_update); |
| 20880 | |||
| 20881 |
2/2✓ Branch 0 taken 2044184 times.
✓ Branch 1 taken 105292654 times.
|
107336838 | if (trx->lock.start_stmt) { |
| 20882 | 2044184 | trx->lock.start_stmt = false; | |
| 20883 | 2044184 | TrxInInnoDB::end_stmt(trx); | |
| 20884 | } | ||
| 20885 | |||
| 20886 | 107336908 | return (0); | |
| 20887 | } | ||
| 20888 | |||
| 20889 | /** | ||
| 20890 | MySQL calls this method at the end of each statement */ | ||
| 20891 | |||
| 20892 | 107335049 | int ha_innobase::reset() { return (end_stmt()); } | |
| 20893 | |||
| 20894 | /** MySQL calls this function at the start of each SQL statement inside LOCK | ||
| 20895 | TABLES. Inside LOCK TABLES the "::external_lock" method does not work to mark | ||
| 20896 | SQL statement borders. Note also a special case: if a temporary table is | ||
| 20897 | created inside LOCK TABLES, MySQL has not called external_lock() at all on | ||
| 20898 | that table. | ||
| 20899 | MySQL-5.0 also calls this before each statement in an execution of a stored | ||
| 20900 | procedure. To make the execution more deterministic for binlogging, MySQL-5.0 | ||
| 20901 | locks all tables involved in a stored procedure with full explicit table locks | ||
| 20902 | (thd_in_lock_tables(thd) holds in store_lock()) before executing the procedure. | ||
| 20903 | @param[in] thd handle to the user thread | ||
| 20904 | @param[in] lock_type lock type | ||
| 20905 | @return 0 or error code */ | ||
| 20906 | 2126719 | int ha_innobase::start_stmt(THD *thd, thr_lock_type lock_type) { | |
| 20907 | 2126719 | trx_t *trx = m_prebuilt->trx; | |
| 20908 | |||
| 20909 |
1/2✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
|
2126719 | DBUG_TRACE; |
| 20910 | |||
| 20911 |
1/2✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
|
2126719 | update_thd(thd); |
| 20912 | |||
| 20913 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2126719 times.
|
2126719 | ut_ad(m_prebuilt->table != nullptr); |
| 20914 | |||
| 20915 |
1/2✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
|
2126719 | TrxInInnoDB trx_in_innodb(trx); |
| 20916 | |||
| 20917 |
2/4✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2126719 times.
|
2126719 | if (m_prebuilt->table->is_intrinsic()) { |
| 20918 | ✗ | if (thd_sql_command(thd) == SQLCOM_ALTER_TABLE) { | |
| 20919 | ✗ | return HA_ERR_WRONG_COMMAND; | |
| 20920 | } | ||
| 20921 | |||
| 20922 | ✗ | return 0; | |
| 20923 | } | ||
| 20924 | |||
| 20925 | 2126719 | trx = m_prebuilt->trx; | |
| 20926 | |||
| 20927 |
1/2✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
|
2126719 | innobase_srv_conc_force_exit_innodb(trx); |
| 20928 | |||
| 20929 | /* Reset the AUTOINC statement level counter for multi-row INSERTs. */ | ||
| 20930 | 2126719 | trx->n_autoinc_rows = 0; | |
| 20931 | |||
| 20932 | 2126719 | m_prebuilt->sql_stat_start = true; | |
| 20933 | 2126719 | m_prebuilt->hint_need_to_fetch_extra_cols = 0; | |
| 20934 |
1/2✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
|
2126719 | reset_template(); |
| 20935 | |||
| 20936 |
7/8✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23786 times.
✓ Branch 3 taken 2102933 times.
✓ Branch 4 taken 23677 times.
✓ Branch 5 taken 109 times.
✓ Branch 6 taken 27 times.
✓ Branch 7 taken 2126692 times.
|
2150396 | if (m_prebuilt->table->is_temporary() && m_mysql_has_locked && |
| 20937 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 23650 times.
|
23677 | m_prebuilt->select_lock_type == LOCK_NONE) { |
| 20938 | dberr_t error; | ||
| 20939 | |||
| 20940 |
3/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 25 times.
|
27 | switch (thd_sql_command(thd)) { |
| 20941 | 2 | case SQLCOM_INSERT: | |
| 20942 | case SQLCOM_UPDATE: | ||
| 20943 | case SQLCOM_DELETE: | ||
| 20944 | case SQLCOM_REPLACE: | ||
| 20945 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | init_table_handle_for_HANDLER(); |
| 20946 | 2 | m_prebuilt->select_lock_type = LOCK_X; | |
| 20947 | 2 | m_stored_select_lock_type = LOCK_X; | |
| 20948 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | error = row_lock_table(m_prebuilt); |
| 20949 | |||
| 20950 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (error != DB_SUCCESS) { |
| 20951 | ✗ | int st = convert_error_code_to_mysql(error, 0, thd); | |
| 20952 | ✗ | return st; | |
| 20953 | } | ||
| 20954 | 2 | break; | |
| 20955 | } | ||
| 20956 | } | ||
| 20957 | |||
| 20958 |
2/2✓ Branch 0 taken 109 times.
✓ Branch 1 taken 2126610 times.
|
2126719 | if (!m_mysql_has_locked) { |
| 20959 | /* This handle is for a temporary table created inside | ||
| 20960 | this same LOCK TABLES; since MySQL does NOT call external_lock | ||
| 20961 | in this case, we must use x-row locks inside InnoDB to be | ||
| 20962 | prepared for an update of a row */ | ||
| 20963 | |||
| 20964 | 109 | m_prebuilt->select_lock_type = LOCK_X; | |
| 20965 | |||
| 20966 |
2/2✓ Branch 0 taken 93349 times.
✓ Branch 1 taken 2033120 times.
|
2126469 | } else if ((trx->isolation_level != TRX_ISO_SERIALIZABLE && |
| 20967 |
7/8✓ Branch 0 taken 2126469 times.
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 93349 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82789 times.
✓ Branch 5 taken 10560 times.
✓ Branch 6 taken 10607 times.
✓ Branch 7 taken 2116003 times.
|
4336009 | lock_type == TL_READ && thd_sql_command(thd) == SQLCOM_SELECT) || |
| 20968 |
5/6✓ Branch 0 taken 2116050 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 276 times.
✓ Branch 3 taken 2115774 times.
✓ Branch 4 taken 233 times.
✓ Branch 5 taken 43 times.
|
2116050 | (trx->skip_gap_locks() && |
| 20969 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 196 times.
|
233 | (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) && |
| 20970 |
3/4✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 13 times.
|
80 | (thd_sql_command(thd) == SQLCOM_INSERT_SELECT || |
| 20971 |
3/4✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 4 times.
|
67 | thd_sql_command(thd) == SQLCOM_REPLACE_SELECT || |
| 20972 |
3/4✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 26 times.
|
63 | thd_sql_command(thd) == SQLCOM_UPDATE || |
| 20973 |
3/4✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 33 times.
|
37 | thd_sql_command(thd) == SQLCOM_CREATE_TABLE))) { |
| 20974 | /* For other than temporary tables, we obtain | ||
| 20975 | no lock for consistent read (plain SELECT). | ||
| 20976 | |||
| 20977 | If this session is using READ COMMITTED or READ | ||
| 20978 | UNCOMMITTED isolation level and MySQL is doing INSERT | ||
| 20979 | INTO... SELECT or REPLACE INTO...SELECT or UPDATE ... | ||
| 20980 | = (SELECT ...) or CREATE ... SELECT... without FOR | ||
| 20981 | UPDATE or IN SHARE MODE in select, then we use | ||
| 20982 | consistent read for select. | ||
| 20983 | |||
| 20984 | See also similar code in ha_innobase::store_lock(). */ | ||
| 20985 | |||
| 20986 | 10607 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 20987 | } else { | ||
| 20988 | /* Not a consistent read: restore the | ||
| 20989 | select_lock_type value. The value of | ||
| 20990 | stored_select_lock_type was decided in: | ||
| 20991 | 1) ::store_lock(), | ||
| 20992 | 2) ::external_lock(), | ||
| 20993 | 3) ::init_table_handle_for_HANDLER(). */ | ||
| 20994 | |||
| 20995 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2116003 times.
|
2116003 | ut_a(m_stored_select_lock_type != LOCK_NONE_UNSET); |
| 20996 | |||
| 20997 | 2116003 | m_prebuilt->select_lock_type = m_stored_select_lock_type; | |
| 20998 | } | ||
| 20999 | |||
| 21000 | 2126719 | *trx->detailed_error = 0; | |
| 21001 | |||
| 21002 |
1/2✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
|
2126719 | innobase_register_trx(ht, thd, trx); |
| 21003 | |||
| 21004 |
3/4✓ Branch 0 taken 2126719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66958 times.
✓ Branch 3 taken 2059761 times.
|
2126719 | if (!trx_is_started(trx)) { |
| 21005 | 66958 | ++trx->will_lock; | |
| 21006 | } | ||
| 21007 | |||
| 21008 | /* Only do it once per transaction. */ | ||
| 21009 |
4/4✓ Branch 0 taken 2044185 times.
✓ Branch 1 taken 82534 times.
✓ Branch 2 taken 2044184 times.
✓ Branch 3 taken 1 times.
|
2126719 | if (!trx->lock.start_stmt && lock_type != TL_UNLOCK) { |
| 21010 | 2044184 | trx->lock.start_stmt = true; | |
| 21011 |
1/2✓ Branch 0 taken 2044184 times.
✗ Branch 1 not taken.
|
2044184 | TrxInInnoDB::begin_stmt(trx); |
| 21012 | } | ||
| 21013 | |||
| 21014 | 2126719 | return 0; | |
| 21015 | 2126719 | } | |
| 21016 | |||
| 21017 | 104455109 | trx_t::isolation_level_t innobase_trx_map_isolation_level( | |
| 21018 | enum_tx_isolation iso) { | ||
| 21019 | trx_t::isolation_level_t trx_isolation_level; | ||
| 21020 | |||
| 21021 |
4/5✓ Branch 0 taken 29533253 times.
✓ Branch 1 taken 62877615 times.
✓ Branch 2 taken 20402 times.
✓ Branch 3 taken 12024165 times.
✗ Branch 4 not taken.
|
104455109 | switch (iso) { |
| 21022 | 29533253 | case ISO_REPEATABLE_READ: | |
| 21023 | 29533253 | trx_isolation_level = TRX_ISO_REPEATABLE_READ; | |
| 21024 | 29533253 | break; | |
| 21025 | 62877615 | case ISO_READ_COMMITTED: | |
| 21026 | 62877615 | trx_isolation_level = TRX_ISO_READ_COMMITTED; | |
| 21027 | 62877615 | break; | |
| 21028 | 20402 | case ISO_SERIALIZABLE: | |
| 21029 | 20402 | trx_isolation_level = TRX_ISO_SERIALIZABLE; | |
| 21030 | 20402 | break; | |
| 21031 | 12024165 | case ISO_READ_UNCOMMITTED: | |
| 21032 | 12024165 | trx_isolation_level = TRX_ISO_READ_UNCOMMITTED; | |
| 21033 | 12024165 | break; | |
| 21034 | ✗ | default: | |
| 21035 | ✗ | ut_error; | |
| 21036 | } | ||
| 21037 | |||
| 21038 | 104455435 | return trx_isolation_level; | |
| 21039 | } | ||
| 21040 | |||
| 21041 | /** As MySQL will execute an external lock for every new table it uses when it | ||
| 21042 | starts to process an SQL statement (an exception is when MySQL calls | ||
| 21043 | start_stmt for the handle) we can use this function to store the pointer to | ||
| 21044 | the THD in the handle. We will also use this function to communicate | ||
| 21045 | to InnoDB that a new SQL statement has started and that we must store a | ||
| 21046 | savepoint to our transaction handle, so that we are able to roll back | ||
| 21047 | the SQL statement in case of an error. | ||
| 21048 | @return 0 */ | ||
| 21049 | |||
| 21050 | 210486321 | int ha_innobase::external_lock(THD *thd, /*!< in: handle to the user thread */ | |
| 21051 | int lock_type) /*!< in: lock type */ | ||
| 21052 | { | ||
| 21053 |
1/2✓ Branch 0 taken 210489183 times.
✗ Branch 1 not taken.
|
210486321 | DBUG_TRACE; |
| 21054 |
5/8✓ Branch 0 taken 210488859 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 210488801 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12628 times.
✓ Branch 5 taken 210476173 times.
✓ Branch 6 taken 12628 times.
✗ Branch 7 not taken.
|
210489183 | DBUG_PRINT("enter", ("lock_type: %d", lock_type)); |
| 21055 | |||
| 21056 |
1/2✓ Branch 0 taken 210488280 times.
✗ Branch 1 not taken.
|
210488801 | update_thd(thd); |
| 21057 | |||
| 21058 | 210488280 | trx_t *trx = m_prebuilt->trx; | |
| 21059 | |||
| 21060 |
1/2✓ Branch 0 taken 210489068 times.
✗ Branch 1 not taken.
|
210488280 | enum_sql_command sql_command = (enum_sql_command)thd_sql_command(thd); |
| 21061 | |||
| 21062 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 210488676 times.
|
210489068 | ut_ad(m_prebuilt->table); |
| 21063 | |||
| 21064 |
2/4✓ Branch 0 taken 210488240 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 210488240 times.
|
210488676 | if (m_prebuilt->table->is_intrinsic()) { |
| 21065 | ✗ | if (sql_command == SQLCOM_ALTER_TABLE) { | |
| 21066 | ✗ | return HA_ERR_WRONG_COMMAND; | |
| 21067 | } | ||
| 21068 | |||
| 21069 | ✗ | TrxInInnoDB::begin_stmt(trx); | |
| 21070 | |||
| 21071 | ✗ | return 0; | |
| 21072 | } | ||
| 21073 | |||
| 21074 | /* Statement based binlogging does not work in isolation level | ||
| 21075 | READ UNCOMMITTED and READ COMMITTED since the necessary | ||
| 21076 | locks cannot be taken. In this case, we print an | ||
| 21077 | informative error message and return with an error. | ||
| 21078 | Note: decide_logging_format would give the same error message, | ||
| 21079 | except it cannot give the extra details. */ | ||
| 21080 | |||
| 21081 |
3/4✓ Branch 0 taken 26195987 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 571745 times.
✓ Branch 3 taken 25624242 times.
|
26196058 | if (lock_type == F_WRLCK && !(table_flags() & HA_BINLOG_STMT_CAPABLE) && |
| 21082 |
3/4✓ Branch 0 taken 571705 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11264 times.
✓ Branch 3 taken 560441 times.
|
571745 | thd_binlog_format(thd) == BINLOG_FORMAT_STMT && |
| 21083 |
10/12✓ Branch 0 taken 26196058 times.
✓ Branch 1 taken 184292182 times.
✓ Branch 2 taken 11264 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11258 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 11258 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
✓ Branch 9 taken 11234 times.
✓ Branch 10 taken 24 times.
✓ Branch 11 taken 210488105 times.
|
236684187 | thd_binlog_filter_ok(thd) && thd_sqlcom_can_generate_row_events(thd)) { |
| 21084 | 24 | bool skip = false; | |
| 21085 | |||
| 21086 | /* used by test case */ | ||
| 21087 |
2/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
|
24 | DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = true;); |
| 21088 | |||
| 21089 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | if (!skip) { |
| 21090 | #ifdef WITH_WSREP | ||
| 21091 | 24 | bool sql_log_bin_on = thd->variables.option_bits & OPTION_BIN_LOG; | |
| 21092 |
4/4✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 1 times.
|
47 | if (sql_log_bin_on && |
| 21093 |
2/8✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
23 | (!wsrep_on(thd) || wsrep_thd_is_local(m_user_thd))) { |
| 21094 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), |
| 21095 | " InnoDB is limited to row-logging when" | ||
| 21096 | " transaction isolation level is" | ||
| 21097 | " READ COMMITTED or READ UNCOMMITTED."); | ||
| 21098 | 23 | return HA_ERR_LOGGING_IMPOSSIBLE; | |
| 21099 | } | ||
| 21100 | #else | ||
| 21101 | my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), | ||
| 21102 | " InnoDB is limited to row-logging when" | ||
| 21103 | " transaction isolation level is" | ||
| 21104 | " READ COMMITTED or READ UNCOMMITTED."); | ||
| 21105 | return HA_ERR_LOGGING_IMPOSSIBLE; | ||
| 21106 | #endif /* WITH_WSREP */ | ||
| 21107 | } | ||
| 21108 | } | ||
| 21109 | |||
| 21110 | /* Check for UPDATEs in read-only mode. */ | ||
| 21111 |
4/4✓ Branch 0 taken 147307 times.
✓ Branch 1 taken 210340799 times.
✓ Branch 2 taken 146997 times.
✓ Branch 3 taken 310 times.
|
210488106 | if (srv_read_only_mode && |
| 21112 |
4/4✓ Branch 0 taken 146679 times.
✓ Branch 1 taken 318 times.
✓ Branch 2 taken 146678 times.
✓ Branch 3 taken 1 times.
|
146997 | (sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_INSERT || |
| 21113 |
2/4✓ Branch 0 taken 146678 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 146678 times.
✗ Branch 3 not taken.
|
146678 | sql_command == SQLCOM_REPLACE || sql_command == SQLCOM_DROP_TABLE || |
| 21114 |
2/4✓ Branch 0 taken 146678 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 146678 times.
|
146678 | sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE || |
| 21115 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 146678 times.
✗ Branch 3 not taken.
|
146678 | (sql_command == SQLCOM_CREATE_TABLE && lock_type == F_WRLCK) || |
| 21116 |
3/4✓ Branch 0 taken 146678 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 146375 times.
✓ Branch 3 taken 303 times.
|
146678 | sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_DROP_INDEX || |
| 21117 |
2/2✓ Branch 0 taken 146372 times.
✓ Branch 1 taken 3 times.
|
146375 | sql_command == SQLCOM_DELETE || |
| 21118 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 146368 times.
|
146372 | sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY || |
| 21119 | sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) { | ||
| 21120 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 939 times.
|
939 | if (sql_command == SQLCOM_CREATE_TABLE) { |
| 21121 | ✗ | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_INNODB_READ_ONLY); | |
| 21122 | ✗ | return HA_ERR_INNODB_READ_ONLY; | |
| 21123 | } else { | ||
| 21124 |
1/2✓ Branch 0 taken 939 times.
✗ Branch 1 not taken.
|
939 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 21125 | 939 | return HA_ERR_TABLE_READONLY; | |
| 21126 | } | ||
| 21127 | } | ||
| 21128 | |||
| 21129 | 210487167 | m_prebuilt->sql_stat_start = true; | |
| 21130 | 210487167 | m_prebuilt->hint_need_to_fetch_extra_cols = 0; | |
| 21131 | |||
| 21132 |
1/2✓ Branch 0 taken 210486582 times.
✗ Branch 1 not taken.
|
210487167 | reset_template(); |
| 21133 | |||
| 21134 |
4/4✓ Branch 0 taken 398 times.
✓ Branch 1 taken 409 times.
✓ Branch 2 taken 210485633 times.
✓ Branch 3 taken 142 times.
|
210486582 | switch (m_prebuilt->table->quiesce) { |
| 21135 | 398 | case QUIESCE_START: | |
| 21136 | /* Check for FLUSH TABLE t WITH READ LOCK; */ | ||
| 21137 |
4/6✓ Branch 0 taken 398 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 395 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 395 times.
✗ Branch 5 not taken.
|
398 | if (!srv_read_only_mode && sql_command == SQLCOM_FLUSH && |
| 21138 | lock_type == F_RDLCK) { | ||
| 21139 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 393 times.
|
395 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 21140 | 2 | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 21141 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ER_TABLESPACE_DISCARDED, table->s->table_name.str); |
| 21142 | |||
| 21143 | 2 | return HA_ERR_NO_SUCH_TABLE; | |
| 21144 | } | ||
| 21145 | |||
| 21146 |
1/2✓ Branch 0 taken 393 times.
✗ Branch 1 not taken.
|
393 | row_quiesce_table_start(m_prebuilt->table, trx); |
| 21147 | |||
| 21148 | /* Use the transaction instance to track UNLOCK | ||
| 21149 | TABLES. It can be done via START TRANSACTION; too | ||
| 21150 | implicitly. */ | ||
| 21151 | |||
| 21152 | 393 | ++trx->flush_tables; | |
| 21153 | } | ||
| 21154 | 396 | break; | |
| 21155 | |||
| 21156 | 409 | case QUIESCE_COMPLETE: | |
| 21157 | /* Check for UNLOCK TABLES; implicit or explicit | ||
| 21158 | or trx interruption. */ | ||
| 21159 |
6/6✓ Branch 0 taken 397 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 393 times.
✓ Branch 4 taken 393 times.
✓ Branch 5 taken 16 times.
|
413 | if (trx->flush_tables > 0 && |
| 21160 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | (lock_type == F_UNLCK || trx_is_interrupted(trx))) { |
| 21161 |
1/2✓ Branch 0 taken 393 times.
✗ Branch 1 not taken.
|
393 | row_quiesce_table_complete(m_prebuilt->table, trx); |
| 21162 | |||
| 21163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 393 times.
|
393 | ut_a(trx->flush_tables > 0); |
| 21164 | 393 | --trx->flush_tables; | |
| 21165 | } | ||
| 21166 | |||
| 21167 | 409 | break; | |
| 21168 | |||
| 21169 | 210485633 | case QUIESCE_NONE: | |
| 21170 | 210485633 | break; | |
| 21171 | } | ||
| 21172 | |||
| 21173 |
2/2✓ Branch 0 taken 26194376 times.
✓ Branch 1 taken 184292204 times.
|
210486580 | if (lock_type == F_WRLCK) { |
| 21174 | /* If this is a SELECT, then it is in UPDATE TABLE ... | ||
| 21175 | or SELECT ... FOR UPDATE */ | ||
| 21176 | 26194376 | m_prebuilt->select_lock_type = LOCK_X; | |
| 21177 | 26194376 | m_stored_select_lock_type = LOCK_X; | |
| 21178 | } | ||
| 21179 | |||
| 21180 |
4/6✓ Branch 0 taken 79049881 times.
✓ Branch 1 taken 131436699 times.
✓ Branch 2 taken 79049881 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 210486258 times.
|
210486580 | ut_ad(!(lock_type == F_RDLCK && m_prebuilt->select_lock_type == LOCK_X)); |
| 21181 | |||
| 21182 |
2/2✓ Branch 0 taken 105244320 times.
✓ Branch 1 taken 105241938 times.
|
210486258 | if (lock_type != F_UNLCK) { |
| 21183 | /* MySQL is setting a new table lock */ | ||
| 21184 | |||
| 21185 | 105244320 | *trx->detailed_error = 0; | |
| 21186 | |||
| 21187 |
1/2✓ Branch 0 taken 105244784 times.
✗ Branch 1 not taken.
|
105244320 | innobase_register_trx(ht, thd, trx); |
| 21188 | |||
| 21189 | /* | ||
| 21190 | For reads we will use LOCK_NONE, LOCK_S or LOCK_X according to this chart: | ||
| 21191 | +-----------------------------------------+ | ||
| 21192 | | is_dd_table or skip_locking | | ||
| 21193 | +----------------------------------+------+ | ||
| 21194 | | false | true | | ||
| 21195 | +----------------------------------| | | ||
| 21196 | | TRANSACTION ISOLATION LEVEL | | | ||
| 21197 | +----------------+-----------------+ | | ||
| 21198 | | < SERIALIZABLE | = SERIALIZABLE | | | ||
| 21199 | +--------------------+----------------+-----------------+------+ | ||
| 21200 | | non-locking SELECT | NONE [1] | S [3] | NONE | | ||
| 21201 | | SELECT FOR SHARE | S [2] | S | NONE | | ||
| 21202 | | SELECT FOR UPDATE | X | X | X | | ||
| 21203 | +--------------------+----------------+-----------------+------+ | ||
| 21204 | Where LOCK_NONE means a non-locking consistent reads via read-view, and | ||
| 21205 | `no_read_locking` is set to `true` by Server calling | ||
| 21206 | ha_extra(). | ||
| 21207 | Notes: | ||
| 21208 | [1,2] The server layer calls external_lock(..,F_RDLCK) which retains the old | ||
| 21209 | value of select_lock_type before the call. In most cases it is the value | ||
| 21210 | set by a previous call to store_lock(..): | ||
| 21211 | [1] For a non-locking SELECT the Server layer calls store_lock(..,TL_READ) | ||
| 21212 | which sets select_lock_type = LOCK_NONE, except for ACL tables which | ||
| 21213 | treat it as in [1]. | ||
| 21214 | [2] In case of SELECT FOR SHARE the Server layer calls | ||
| 21215 | store_lock(..,TL_READ_WITH_SHARED_LOCKS) which sets | ||
| 21216 | select_lock_type = LOCK_S | ||
| 21217 | [3] An exception is consistent reads in the AUTOCOMMIT=1 mode: | ||
| 21218 | we know that they are read-only transactions, and they can be serialized | ||
| 21219 | also if performed as consistent reads. Thus we use LOCK_NONE for them. | ||
| 21220 | |||
| 21221 | For non-SELECT commands, there may be still possibility of setting | ||
| 21222 | skip_locking=1. E.g., | ||
| 21223 | - UPDATE ... WHERE ... (SELECT... acl_table); | ||
| 21224 | - DELETE ... WHERE ... (SELECT... acl_table); | ||
| 21225 | The first entry 'non-locking SELECT' in above table applies in these case. | ||
| 21226 | */ | ||
| 21227 |
2/2✓ Branch 0 taken 79049994 times.
✓ Branch 1 taken 26194790 times.
|
105244784 | if (lock_type == F_RDLCK) { |
| 21228 | /** | ||
| 21229 | To limit range of circumstances under which transaction's isolation | ||
| 21230 | level can be compromised, we allow disabling readlocks only for DD | ||
| 21231 | and ACL tables. | ||
| 21232 | */ | ||
| 21233 |
8/10✓ Branch 0 taken 2331650 times.
✓ Branch 1 taken 76718344 times.
✓ Branch 2 taken 22534 times.
✓ Branch 3 taken 2309116 times.
✓ Branch 4 taken 22534 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22534 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 126 times.
✓ Branch 9 taken 79049834 times.
|
79049994 | ut_ad(!m_prebuilt->no_read_locking || m_prebuilt->table->is_dd_table || |
| 21234 | is_acl_table(table)); | ||
| 21235 | |||
| 21236 |
4/4✓ Branch 0 taken 2491872 times.
✓ Branch 1 taken 76557962 times.
✓ Branch 2 taken 22534 times.
✓ Branch 3 taken 2469338 times.
|
79049834 | if (m_prebuilt->table->is_dd_table || m_prebuilt->no_read_locking) { |
| 21237 | 76580496 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 21238 | 76580496 | m_stored_select_lock_type = LOCK_NONE; | |
| 21239 | 4940093 | } else if (trx->isolation_level == TRX_ISO_SERIALIZABLE && | |
| 21240 |
6/6✓ Branch 0 taken 1417 times.
✓ Branch 1 taken 2467921 times.
✓ Branch 2 taken 340 times.
✓ Branch 3 taken 1077 times.
✓ Branch 4 taken 33 times.
✓ Branch 5 taken 2469305 times.
|
2469678 | m_prebuilt->select_lock_type == LOCK_NONE && |
| 21241 |
3/4✓ Branch 0 taken 340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 307 times.
|
340 | thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { |
| 21242 | 33 | m_prebuilt->select_lock_type = LOCK_S; | |
| 21243 | 33 | m_stored_select_lock_type = LOCK_S; | |
| 21244 | } else { | ||
| 21245 | // Retain value set earlier for example via store_lock() | ||
| 21246 | // which is LOCK_S or LOCK_NONE | ||
| 21247 |
4/6✓ Branch 0 taken 1383574 times.
✓ Branch 1 taken 1085731 times.
✓ Branch 2 taken 1383574 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2469306 times.
|
2469305 | ut_ad(m_prebuilt->select_lock_type == LOCK_S || |
| 21248 | m_prebuilt->select_lock_type == LOCK_NONE); | ||
| 21249 | } | ||
| 21250 | } | ||
| 21251 | |||
| 21252 | /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK | ||
| 21253 | TABLES if AUTOCOMMIT=1. It does not make much sense to acquire | ||
| 21254 | an InnoDB table lock if it is released immediately at the end | ||
| 21255 | of LOCK TABLES, and InnoDB's table locks in that case cause | ||
| 21256 | VERY easily deadlocks. | ||
| 21257 | |||
| 21258 | We do not set InnoDB table locks if user has not explicitly | ||
| 21259 | requested a table lock. Note that thd_in_lock_tables(thd) | ||
| 21260 | can hold in some cases, e.g., at the start of a stored | ||
| 21261 | procedure call (SQLCOM_CALL). */ | ||
| 21262 | |||
| 21263 |
2/2✓ Branch 0 taken 27280468 times.
✓ Branch 1 taken 77964157 times.
|
105244625 | if (m_prebuilt->select_lock_type != LOCK_NONE) { |
| 21264 |
3/4✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3353 times.
✓ Branch 3 taken 2 times.
|
3355 | if (sql_command == SQLCOM_LOCK_TABLES && THDVAR(thd, table_locks) && |
| 21265 |
7/8✓ Branch 0 taken 3355 times.
✓ Branch 1 taken 27277113 times.
✓ Branch 2 taken 3353 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 154 times.
✓ Branch 5 taken 3199 times.
✓ Branch 6 taken 154 times.
✓ Branch 7 taken 27280314 times.
|
27283977 | thd_test_options(thd, OPTION_NOT_AUTOCOMMIT) && |
| 21266 |
2/4✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
|
154 | thd_in_lock_tables(thd)) { |
| 21267 |
1/2✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
|
154 | dberr_t error = row_lock_table(m_prebuilt); |
| 21268 | |||
| 21269 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
|
154 | if (error != DB_SUCCESS) { |
| 21270 | ✗ | return convert_error_code_to_mysql(error, 0, thd); | |
| 21271 | } | ||
| 21272 | } | ||
| 21273 | |||
| 21274 | 27280468 | trx->mysql_n_tables_locked++; | |
| 21275 | } | ||
| 21276 | |||
| 21277 | 105244625 | trx->n_mysql_tables_in_use++; | |
| 21278 | 105244625 | m_mysql_has_locked = true; | |
| 21279 | |||
| 21280 |
7/8✓ Branch 0 taken 105244845 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87446491 times.
✓ Branch 3 taken 17798354 times.
✓ Branch 4 taken 77631973 times.
✓ Branch 5 taken 9814518 times.
✓ Branch 6 taken 9814868 times.
✓ Branch 7 taken 95429977 times.
|
182876598 | if (!trx_is_started(trx) && (m_prebuilt->select_lock_type != LOCK_NONE || |
| 21281 |
2/2✓ Branch 0 taken 353 times.
✓ Branch 1 taken 77631620 times.
|
77631973 | m_stored_select_lock_type != LOCK_NONE)) { |
| 21282 | 9814868 | ++trx->will_lock; | |
| 21283 | } | ||
| 21284 | |||
| 21285 |
1/2✓ Branch 0 taken 105245142 times.
✗ Branch 1 not taken.
|
105244845 | TrxInInnoDB::begin_stmt(trx); |
| 21286 | |||
| 21287 | #ifdef UNIV_DEBUG | ||
| 21288 |
6/8✓ Branch 0 taken 105245162 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105245081 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 74323645 times.
✓ Branch 5 taken 30921436 times.
✓ Branch 6 taken 74323645 times.
✓ Branch 7 taken 30921416 times.
|
105245142 | if (thd != nullptr && thd_tx_is_dd_trx(thd)) { |
| 21289 | 74323645 | trx->is_dd_trx = true; | |
| 21290 | } | ||
| 21291 | #endif /* UNIV_DEBUG */ | ||
| 21292 | 105245061 | return 0; | |
| 21293 | } else { | ||
| 21294 |
1/2✓ Branch 0 taken 105242234 times.
✗ Branch 1 not taken.
|
105241938 | TrxInInnoDB::end_stmt(trx); |
| 21295 | |||
| 21296 |
3/4✓ Branch 0 taken 96504964 times.
✓ Branch 1 taken 8737270 times.
✓ Branch 2 taken 96505667 times.
✗ Branch 3 not taken.
|
105242234 | DEBUG_SYNC_C("ha_innobase_end_statement"); |
| 21297 | } | ||
| 21298 | |||
| 21299 | /* MySQL is releasing a table lock */ | ||
| 21300 | |||
| 21301 | 105242937 | trx->n_mysql_tables_in_use--; | |
| 21302 | 105242937 | m_mysql_has_locked = false; | |
| 21303 | |||
| 21304 |
1/2✓ Branch 0 taken 105242458 times.
✗ Branch 1 not taken.
|
105242937 | innobase_srv_conc_force_exit_innodb(trx); |
| 21305 | |||
| 21306 | /* If the MySQL lock count drops to zero we know that the current SQL | ||
| 21307 | statement has ended */ | ||
| 21308 | |||
| 21309 |
2/2✓ Branch 0 taken 31071705 times.
✓ Branch 1 taken 74170753 times.
|
105242458 | if (trx->n_mysql_tables_in_use == 0) { |
| 21310 | 31071705 | trx->mysql_n_tables_locked = 0; | |
| 21311 | 31071705 | m_prebuilt->used_in_HANDLER = false; | |
| 21312 | |||
| 21313 |
3/4✓ Branch 0 taken 31071606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19492389 times.
✓ Branch 3 taken 11579217 times.
|
31071705 | if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { |
| 21314 |
3/4✓ Branch 0 taken 19491557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 699181 times.
✓ Branch 3 taken 18792376 times.
|
19492389 | if (trx_is_started(trx)) { |
| 21315 |
1/2✓ Branch 0 taken 699181 times.
✗ Branch 1 not taken.
|
699181 | innobase_commit(ht, thd, true); |
| 21316 | } else { | ||
| 21317 | /* Since the trx state is TRX_NOT_STARTED, | ||
| 21318 | trx_commit() will not be called. Reset | ||
| 21319 | trx->is_dd_trx here */ | ||
| 21320 | 18792376 | ut_d(trx->is_dd_trx = false); | |
| 21321 | } | ||
| 21322 | |||
| 21323 |
4/4✓ Branch 0 taken 385983 times.
✓ Branch 1 taken 11193234 times.
✓ Branch 2 taken 9828 times.
✓ Branch 3 taken 11569386 times.
|
11965197 | } else if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && |
| 21324 |
3/4✓ Branch 0 taken 385980 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9828 times.
✓ Branch 3 taken 376152 times.
|
385983 | MVCC::is_view_active(trx->read_view)) { |
| 21325 |
1/2✓ Branch 0 taken 9828 times.
✗ Branch 1 not taken.
|
9828 | mutex_enter(&trx_sys->mutex); |
| 21326 | |||
| 21327 |
1/2✓ Branch 0 taken 9828 times.
✗ Branch 1 not taken.
|
9828 | trx_sys->mvcc->view_close(trx->read_view, true); |
| 21328 | |||
| 21329 |
1/2✓ Branch 0 taken 9828 times.
✗ Branch 1 not taken.
|
9828 | mutex_exit(&trx_sys->mutex); |
| 21330 | } | ||
| 21331 | } | ||
| 21332 | |||
| 21333 |
5/8✓ Branch 0 taken 105241863 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79759484 times.
✓ Branch 3 taken 25482379 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 79759484 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 105241863 times.
|
105241524 | if (!trx_is_started(trx) && lock_type != F_UNLCK && |
| 21334 | ✗ | (m_prebuilt->select_lock_type != LOCK_NONE || | |
| 21335 | ✗ | m_stored_select_lock_type != LOCK_NONE)) { | |
| 21336 | ✗ | ++trx->will_lock; | |
| 21337 | } | ||
| 21338 | |||
| 21339 | 105241863 | return 0; | |
| 21340 | 210487888 | } | |
| 21341 | |||
| 21342 | /** Here we export InnoDB status variables to MySQL. */ | ||
| 21343 | 142028 | static void innodb_export_status() { | |
| 21344 |
1/2✓ Branch 0 taken 142028 times.
✗ Branch 1 not taken.
|
142028 | if (innodb_inited) { |
| 21345 | 142028 | srv_export_innodb_status(); | |
| 21346 | } | ||
| 21347 | 142027 | } | |
| 21348 | |||
| 21349 | /** Implements the SHOW ENGINE INNODB STATUS command. Sends the output of the | ||
| 21350 | InnoDB Monitor to the client. | ||
| 21351 | @param[in] hton the innodb handlerton | ||
| 21352 | @param[in] thd the MySQL query thread of the caller | ||
| 21353 | @param[in] stat_print print function | ||
| 21354 | @return 0 on success */ | ||
| 21355 | 279 | static int innodb_show_status(handlerton *hton, THD *thd, | |
| 21356 | stat_print_fn *stat_print) { | ||
| 21357 | static const char truncated_msg[] = "... truncated...\n"; | ||
| 21358 | 279 | const long MAX_STATUS_SIZE = 1048576; | |
| 21359 | 279 | ulint trx_list_start = ULINT_UNDEFINED; | |
| 21360 | 279 | ulint trx_list_end = ULINT_UNDEFINED; | |
| 21361 | bool ret_val; | ||
| 21362 | |||
| 21363 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | DBUG_TRACE; |
| 21364 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
|
279 | assert(hton == innodb_hton_ptr); |
| 21365 | |||
| 21366 | /* We don't create the temp files or associated | ||
| 21367 | mutexes in read-only-mode */ | ||
| 21368 | |||
| 21369 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
|
279 | if (srv_read_only_mode) { |
| 21370 | ✗ | return 0; | |
| 21371 | } | ||
| 21372 | |||
| 21373 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | trx_t *trx = check_trx_exists(thd); |
| 21374 | |||
| 21375 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | innobase_srv_conc_force_exit_innodb(trx); |
| 21376 | |||
| 21377 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | TrxInInnoDB trx_in_innodb(trx); |
| 21378 | |||
| 21379 | /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE | ||
| 21380 | bytes of text. */ | ||
| 21381 | |||
| 21382 | char *str; | ||
| 21383 | ssize_t flen; | ||
| 21384 | |||
| 21385 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | mutex_enter(&srv_monitor_file_mutex); |
| 21386 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | rewind(srv_monitor_file); |
| 21387 | |||
| 21388 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | srv_printf_innodb_monitor(srv_monitor_file, false, &trx_list_start, |
| 21389 | &trx_list_end); | ||
| 21390 | |||
| 21391 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | os_file_set_eof(srv_monitor_file); |
| 21392 | |||
| 21393 |
2/4✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 279 times.
|
279 | if ((flen = ftell(srv_monitor_file)) < 0) { |
| 21394 | ✗ | flen = 0; | |
| 21395 | } | ||
| 21396 | |||
| 21397 | ssize_t usable_len; | ||
| 21398 | |||
| 21399 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
|
279 | if (flen > MAX_STATUS_SIZE) { |
| 21400 | ✗ | usable_len = MAX_STATUS_SIZE; | |
| 21401 | ✗ | srv_truncated_status_writes++; | |
| 21402 | } else { | ||
| 21403 | 279 | usable_len = flen; | |
| 21404 | } | ||
| 21405 | |||
| 21406 | /* allocate buffer for the string, and | ||
| 21407 | read the contents of the temporary file */ | ||
| 21408 | |||
| 21409 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | str = (char *)my_malloc(PSI_INSTRUMENT_ME, usable_len + 1, MYF(0)); |
| 21410 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 279 times.
|
279 | if (!str) { |
| 21411 | ✗ | mutex_exit(&srv_monitor_file_mutex); | |
| 21412 | ✗ | return 1; | |
| 21413 | } | ||
| 21414 | |||
| 21415 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | rewind(srv_monitor_file); |
| 21416 | |||
| 21417 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | if (flen < MAX_STATUS_SIZE) { |
| 21418 | /* Display the entire output. */ | ||
| 21419 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | flen = fread(str, 1, flen, srv_monitor_file); |
| 21420 | ✗ | } else if (trx_list_end < (ulint)flen && trx_list_start < trx_list_end && | |
| 21421 | ✗ | trx_list_start + (flen - trx_list_end) < | |
| 21422 | MAX_STATUS_SIZE - sizeof truncated_msg - 1) { | ||
| 21423 | /* Omit the beginning of the list of active transactions. */ | ||
| 21424 | ✗ | ssize_t len = fread(str, 1, trx_list_start, srv_monitor_file); | |
| 21425 | |||
| 21426 | ✗ | memcpy(str + len, truncated_msg, sizeof truncated_msg - 1); | |
| 21427 | ✗ | len += sizeof truncated_msg - 1; | |
| 21428 | ✗ | usable_len = (MAX_STATUS_SIZE - 1) - len; | |
| 21429 | ✗ | fseek(srv_monitor_file, static_cast<long>(flen - usable_len), SEEK_SET); | |
| 21430 | ✗ | len += fread(str + len, 1, usable_len, srv_monitor_file); | |
| 21431 | ✗ | flen = len; | |
| 21432 | ✗ | } else { | |
| 21433 | /* Omit the end of the output. */ | ||
| 21434 | ✗ | flen = fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file); | |
| 21435 | } | ||
| 21436 | |||
| 21437 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | mutex_exit(&srv_monitor_file_mutex); |
| 21438 | |||
| 21439 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | ret_val = stat_print(thd, innobase_hton_name, |
| 21440 | static_cast<uint>(strlen(innobase_hton_name)), | ||
| 21441 | STRING_WITH_LEN(""), str, static_cast<uint>(flen)); | ||
| 21442 | |||
| 21443 |
1/2✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
|
279 | my_free(str); |
| 21444 | |||
| 21445 | 279 | return ret_val; | |
| 21446 | 279 | } | |
| 21447 | |||
| 21448 | /** Implements Log_resource lock. | ||
| 21449 | @param[in] hton the innodb handlerton | ||
| 21450 | @return false on success */ | ||
| 21451 | 252 | static bool innobase_lock_hton_log(handlerton *hton) { | |
| 21452 | 252 | bool ret_val = false; | |
| 21453 | |||
| 21454 |
1/2✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
|
252 | DBUG_TRACE; |
| 21455 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
|
252 | assert(hton == innodb_hton_ptr); |
| 21456 | |||
| 21457 |
1/2✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
|
252 | log_position_lock(*log_sys); |
| 21458 | |||
| 21459 | 252 | return ret_val; | |
| 21460 | 252 | } | |
| 21461 | |||
| 21462 | /** Implements Log_resource unlock. | ||
| 21463 | @param[in] hton the innodb handlerton | ||
| 21464 | @return false on success */ | ||
| 21465 | 252 | static bool innobase_unlock_hton_log(handlerton *hton) { | |
| 21466 | 252 | bool ret_val = false; | |
| 21467 | |||
| 21468 |
1/2✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
|
252 | DBUG_TRACE; |
| 21469 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
|
252 | assert(hton == innodb_hton_ptr); |
| 21470 | |||
| 21471 |
1/2✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
|
252 | log_position_unlock(*log_sys); |
| 21472 | |||
| 21473 | 252 | return ret_val; | |
| 21474 | 252 | } | |
| 21475 | |||
| 21476 | /** Implements Log_resource collect_info. | ||
| 21477 | @param[in] hton the innodb handlerton | ||
| 21478 | @param[in] json the JSON dom to receive the log info | ||
| 21479 | @return false on success */ | ||
| 21480 | 251 | static bool innobase_collect_hton_log_info(handlerton *hton, Json_dom *json) { | |
| 21481 | 251 | bool ret_val = false; | |
| 21482 | lsn_t lsn; | ||
| 21483 | lsn_t lsn_checkpoint; | ||
| 21484 | |||
| 21485 |
1/2✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
|
251 | DBUG_TRACE; |
| 21486 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 251 times.
|
251 | assert(hton == innodb_hton_ptr); |
| 21487 | |||
| 21488 |
1/2✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
|
251 | log_position_collect_lsn_info(*log_sys, &lsn, &lsn_checkpoint); |
| 21489 | |||
| 21490 | 251 | Json_object *json_engines = static_cast<Json_object *>(json); | |
| 21491 |
1/2✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
|
251 | Json_object json_innodb; |
| 21492 | 251 | Json_int json_lsn(lsn); | |
| 21493 | 251 | Json_int json_lsn_checkpoint(lsn_checkpoint); | |
| 21494 | |||
| 21495 |
2/4✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251 times.
✗ Branch 3 not taken.
|
251 | ret_val = json_innodb.add_clone("LSN", &json_lsn); |
| 21496 |
1/2✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
|
251 | if (!ret_val) |
| 21497 |
2/4✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251 times.
✗ Branch 3 not taken.
|
251 | ret_val = json_innodb.add_clone("LSN_checkpoint", &json_lsn_checkpoint); |
| 21498 |
3/6✓ Branch 0 taken 251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 251 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 251 times.
✗ Branch 5 not taken.
|
251 | if (!ret_val) ret_val = json_engines->add_clone("InnoDB", &json_innodb); |
| 21499 | |||
| 21500 | 251 | return ret_val; | |
| 21501 | 251 | } | |
| 21502 | |||
| 21503 | /** Callback for collecting mutex statistics */ | ||
| 21504 | struct ShowStatus { | ||
| 21505 | /** For tracking the mutex metrics */ | ||
| 21506 | struct Value { | ||
| 21507 | /** Constructor | ||
| 21508 | @param[in] name Name of the mutex | ||
| 21509 | @param[in] spins Number of spins | ||
| 21510 | @param[in] waits OS waits so far | ||
| 21511 | @param[in] calls Number of calls to enter() */ | ||
| 21512 | ✗ | Value(const char *name, ulint spins, uint64_t waits, uint64_t calls) | |
| 21513 | ✗ | : m_name(name), m_spins(spins), m_waits(waits), m_calls(calls) { | |
| 21514 | /* No op */ | ||
| 21515 | } | ||
| 21516 | |||
| 21517 | /** Mutex name */ | ||
| 21518 | std::string m_name; | ||
| 21519 | |||
| 21520 | /** Spins so far */ | ||
| 21521 | ulint m_spins; | ||
| 21522 | |||
| 21523 | /** Waits so far */ | ||
| 21524 | uint64_t m_waits; | ||
| 21525 | |||
| 21526 | /** Number of calls so far */ | ||
| 21527 | uint64_t m_calls; | ||
| 21528 | }; | ||
| 21529 | |||
| 21530 | /** Order by m_waits, in descending order. */ | ||
| 21531 | struct OrderByWaits { | ||
| 21532 | /** @return true if rhs < lhs */ | ||
| 21533 | ✗ | bool operator()(const Value &lhs, const Value &rhs) const UNIV_NOTHROW { | |
| 21534 | ✗ | return (rhs.m_waits < lhs.m_waits); | |
| 21535 | } | ||
| 21536 | }; | ||
| 21537 | |||
| 21538 | typedef std::vector<Value, ut::allocator<Value>> Values; | ||
| 21539 | |||
| 21540 | /** Collect the individual latch counts */ | ||
| 21541 | struct GetCount { | ||
| 21542 | typedef latch_meta_t::CounterType::Count Count; | ||
| 21543 | |||
| 21544 | /** Constructor | ||
| 21545 | @param[in] name Latch name | ||
| 21546 | @param[in,out] values Put the values here */ | ||
| 21547 | 363 | GetCount(const char *name, Values *values) UNIV_NOTHROW : m_name(name), | |
| 21548 | 363 | m_values(values) { | |
| 21549 | /* No op */ | ||
| 21550 | 363 | } | |
| 21551 | |||
| 21552 | /** Collect the latch metrics. Ignore entries where the | ||
| 21553 | spins and waits are zero. | ||
| 21554 | @param[in] count The latch metrics */ | ||
| 21555 | 13657 | void operator()(const Count *count) UNIV_NOTHROW { | |
| 21556 |
2/4✓ Branch 0 taken 13657 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13657 times.
|
13657 | if (count->m_spins > 0 || count->m_waits > 0) { |
| 21557 | ✗ | m_values->push_back( | |
| 21558 | ✗ | Value(m_name, count->m_spins, count->m_waits, count->m_calls)); | |
| 21559 | } | ||
| 21560 | 13657 | } | |
| 21561 | |||
| 21562 | /** The latch name */ | ||
| 21563 | const char *m_name; | ||
| 21564 | |||
| 21565 | /** For collecting the active mutex stats. */ | ||
| 21566 | Values *m_values; | ||
| 21567 | }; | ||
| 21568 | |||
| 21569 | /** Constructor */ | ||
| 21570 | 3 | ShowStatus() = default; | |
| 21571 | |||
| 21572 | /** Callback for collecting the stats | ||
| 21573 | @param[in] latch_meta Latch meta data | ||
| 21574 | @return always returns true */ | ||
| 21575 | 363 | bool operator()(latch_meta_t &latch_meta) UNIV_NOTHROW { | |
| 21576 |
1/2✓ Branch 0 taken 363 times.
✗ Branch 1 not taken.
|
726 | latch_meta.get_counter()->iterate( |
| 21577 | 363 | GetCount{latch_meta.get_name(), &m_values}); | |
| 21578 | |||
| 21579 | 363 | return (true); | |
| 21580 | } | ||
| 21581 | |||
| 21582 | /** Implements the SHOW MUTEX STATUS command, for mutexes. | ||
| 21583 | The table structure is like so: Engine | Mutex Name | Status | ||
| 21584 | We store the metrics in the "Status" column as: | ||
| 21585 | |||
| 21586 | spins=N,waits=N,calls=N" | ||
| 21587 | |||
| 21588 | The user has to parse the data unfortunately | ||
| 21589 | @param[in,out] thd the MySQL query thread of the caller | ||
| 21590 | @param[in,out] stat_print function for printing statistics | ||
| 21591 | @return true on success. */ | ||
| 21592 | bool to_string(THD *thd, stat_print_fn *stat_print) UNIV_NOTHROW; | ||
| 21593 | |||
| 21594 | /** For collecting the active mutex stats. */ | ||
| 21595 | Values m_values; | ||
| 21596 | }; | ||
| 21597 | |||
| 21598 | /** Implements the SHOW MUTEX STATUS command, for mutexes. | ||
| 21599 | The table structure is like so: Engine | Mutex Name | Status | ||
| 21600 | We store the metrics in the "Status" column as: | ||
| 21601 | |||
| 21602 | spins=N,waits=N,calls=N" | ||
| 21603 | |||
| 21604 | The user has to parse the data unfortunately | ||
| 21605 | @param[in,out] thd the MySQL query thread of the caller | ||
| 21606 | @param[in,out] stat_print function for printing statistics | ||
| 21607 | @return true on success. */ | ||
| 21608 | 3 | bool ShowStatus::to_string(THD *thd, stat_print_fn *stat_print) UNIV_NOTHROW { | |
| 21609 | 3 | uint hton_name_len = (uint)strlen(innobase_hton_name); | |
| 21610 | |||
| 21611 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | std::sort(m_values.begin(), m_values.end(), OrderByWaits()); |
| 21612 | |||
| 21613 | 3 | Values::iterator end = m_values.end(); | |
| 21614 | |||
| 21615 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | for (Values::iterator it = m_values.begin(); it != end; ++it) { |
| 21616 | int name_len; | ||
| 21617 | char name_buf[IO_SIZE]; | ||
| 21618 | |||
| 21619 | ✗ | name_len = snprintf(name_buf, sizeof(name_buf), "%s", it->m_name.c_str()); | |
| 21620 | |||
| 21621 | int status_len; | ||
| 21622 | char status_buf[IO_SIZE]; | ||
| 21623 | |||
| 21624 | ✗ | status_len = snprintf(status_buf, sizeof(status_buf), | |
| 21625 | "spins=%lu,waits=%lu,calls=" TRX_ID_FMT, | ||
| 21626 | ✗ | static_cast<ulong>(it->m_spins), | |
| 21627 | ✗ | static_cast<long>(it->m_waits), it->m_calls); | |
| 21628 | |||
| 21629 | ✗ | if (stat_print(thd, innobase_hton_name, hton_name_len, name_buf, | |
| 21630 | ✗ | static_cast<uint>(name_len), status_buf, | |
| 21631 | ✗ | static_cast<uint>(status_len))) { | |
| 21632 | ✗ | return (false); | |
| 21633 | } | ||
| 21634 | } | ||
| 21635 | |||
| 21636 | 3 | return (true); | |
| 21637 | } | ||
| 21638 | |||
| 21639 | /** Implements the SHOW MUTEX STATUS command, for mutexes. | ||
| 21640 | @param[in,out] hton the innodb handlerton | ||
| 21641 | @param[in,out] thd the MySQL query thread of the caller | ||
| 21642 | @param[in,out] stat_print function for printing statistics | ||
| 21643 | @return 0 on success. */ | ||
| 21644 | 3 | static int innodb_show_mutex_status(handlerton *hton, THD *thd, | |
| 21645 | stat_print_fn *stat_print) { | ||
| 21646 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_TRACE; |
| 21647 | |||
| 21648 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | ShowStatus collector; |
| 21649 | |||
| 21650 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | assert(hton == innodb_hton_ptr); |
| 21651 | |||
| 21652 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | mutex_monitor->iterate(collector); |
| 21653 | |||
| 21654 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (!collector.to_string(thd, stat_print)) { |
| 21655 | ✗ | return 1; | |
| 21656 | } | ||
| 21657 | |||
| 21658 | 3 | return 0; | |
| 21659 | 3 | } | |
| 21660 | |||
| 21661 | /** Implements the SHOW MUTEX STATUS command. | ||
| 21662 | @param[in,out] hton the innodb handlerton | ||
| 21663 | @param[in,out] thd the MySQL query thread of the caller | ||
| 21664 | @param[in,out] stat_print function for printing statistics | ||
| 21665 | @return 0 on success. */ | ||
| 21666 | 3 | static int innodb_show_rwlock_status(handlerton *hton, THD *thd, | |
| 21667 | stat_print_fn *stat_print) { | ||
| 21668 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | DBUG_TRACE; |
| 21669 | |||
| 21670 | 3 | rw_lock_t *block_rwlock = nullptr; | |
| 21671 | 3 | ulint block_rwlock_oswait_count = 0; | |
| 21672 | 3 | uint hton_name_len = (uint)strlen(innobase_hton_name); | |
| 21673 | |||
| 21674 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | assert(hton == innodb_hton_ptr); |
| 21675 | |||
| 21676 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | mutex_enter(&rw_lock_list_mutex); |
| 21677 | |||
| 21678 |
6/10✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10236 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10239 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10236 times.
✓ Branch 9 taken 3 times.
|
10239 | for (auto rw_lock : rw_lock_list) { |
| 21679 |
2/2✓ Branch 0 taken 10073 times.
✓ Branch 1 taken 163 times.
|
10236 | if (rw_lock->count_os_wait == 0) { |
| 21680 | 10191 | continue; | |
| 21681 | } | ||
| 21682 | |||
| 21683 | int buf1len; | ||
| 21684 | char buf1[IO_SIZE]; | ||
| 21685 | |||
| 21686 |
2/2✓ Branch 0 taken 118 times.
✓ Branch 1 taken 45 times.
|
163 | if (rw_lock->is_block_lock) { |
| 21687 | 118 | block_rwlock = rw_lock; | |
| 21688 | 118 | block_rwlock_oswait_count += rw_lock->count_os_wait; | |
| 21689 | |||
| 21690 | 118 | continue; | |
| 21691 | } | ||
| 21692 | |||
| 21693 | 90 | buf1len = snprintf(buf1, sizeof buf1, "rwlock: %s:%lu", | |
| 21694 | innobase_basename(rw_lock->clocation.filename), | ||
| 21695 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | static_cast<ulong>(rw_lock->clocation.line)); |
| 21696 | |||
| 21697 | int buf2len; | ||
| 21698 | char buf2[IO_SIZE]; | ||
| 21699 | |||
| 21700 | 45 | buf2len = snprintf(buf2, sizeof buf2, "waits=%lu", | |
| 21701 | 45 | static_cast<ulong>(rw_lock->count_os_wait)); | |
| 21702 | |||
| 21703 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (stat_print(thd, innobase_hton_name, hton_name_len, buf1, |
| 21704 | 45 | static_cast<uint>(buf1len), buf2, | |
| 21705 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | static_cast<uint>(buf2len))) { |
| 21706 | ✗ | mutex_exit(&rw_lock_list_mutex); | |
| 21707 | |||
| 21708 | ✗ | return 1; | |
| 21709 | } | ||
| 21710 | } | ||
| 21711 | |||
| 21712 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (block_rwlock != nullptr) { |
| 21713 | int buf1len; | ||
| 21714 | char buf1[IO_SIZE]; | ||
| 21715 | |||
| 21716 | 6 | buf1len = snprintf(buf1, sizeof buf1, "sum rwlock: %s:%lu", | |
| 21717 | innobase_basename(block_rwlock->clocation.filename), | ||
| 21718 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | static_cast<ulong>(block_rwlock->clocation.line)); |
| 21719 | |||
| 21720 | int buf2len; | ||
| 21721 | char buf2[IO_SIZE]; | ||
| 21722 | |||
| 21723 | 3 | buf2len = snprintf(buf2, sizeof buf2, "waits=%lu", | |
| 21724 | static_cast<ulong>(block_rwlock_oswait_count)); | ||
| 21725 | |||
| 21726 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (stat_print(thd, innobase_hton_name, hton_name_len, buf1, |
| 21727 | 3 | static_cast<uint>(buf1len), buf2, | |
| 21728 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | static_cast<uint>(buf2len))) { |
| 21729 | ✗ | mutex_exit(&rw_lock_list_mutex); | |
| 21730 | |||
| 21731 | ✗ | return 1; | |
| 21732 | } | ||
| 21733 | } | ||
| 21734 | |||
| 21735 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | mutex_exit(&rw_lock_list_mutex); |
| 21736 | |||
| 21737 | 3 | return 0; | |
| 21738 | 3 | } | |
| 21739 | |||
| 21740 | /** Implements the SHOW MUTEX STATUS command. | ||
| 21741 | @param[in,out] hton the innodb handlerton | ||
| 21742 | @param[in,out] thd the MySQL query thread of the caller | ||
| 21743 | @param[in,out] stat_print function for printing statistics | ||
| 21744 | @return 0 on success. */ | ||
| 21745 | 3 | static int innodb_show_latch_status(handlerton *hton, THD *thd, | |
| 21746 | stat_print_fn *stat_print) { | ||
| 21747 | 3 | int ret = innodb_show_mutex_status(hton, thd, stat_print); | |
| 21748 | |||
| 21749 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret != 0) { |
| 21750 | ✗ | return (ret); | |
| 21751 | } | ||
| 21752 | |||
| 21753 | 3 | return (innodb_show_rwlock_status(hton, thd, stat_print)); | |
| 21754 | } | ||
| 21755 | |||
| 21756 | /** Return 0 on success and non-zero on failure. Note: the bool return type | ||
| 21757 | seems to be abused here, should be an int. | ||
| 21758 | @param[in] hton the innodb handlerton | ||
| 21759 | @param[in] thd the MySQL query thread of the caller | ||
| 21760 | @param[in] stat_print print function | ||
| 21761 | @param[in] stat_type status to show */ | ||
| 21762 | 285 | static bool innobase_show_status(handlerton *hton, THD *thd, | |
| 21763 | stat_print_fn *stat_print, | ||
| 21764 | enum ha_stat_type stat_type) { | ||
| 21765 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 285 times.
|
285 | assert(hton == innodb_hton_ptr); |
| 21766 | |||
| 21767 |
3/4✓ Branch 0 taken 279 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
285 | switch (stat_type) { |
| 21768 | 279 | case HA_ENGINE_STATUS: | |
| 21769 | /* Non-zero return value means there was an error. */ | ||
| 21770 | 279 | return (innodb_show_status(hton, thd, stat_print) != 0); | |
| 21771 | |||
| 21772 | 3 | case HA_ENGINE_MUTEX: | |
| 21773 | 3 | return (innodb_show_latch_status(hton, thd, stat_print) != 0); | |
| 21774 | |||
| 21775 | 3 | case HA_ENGINE_LOGS: | |
| 21776 | /* Not handled */ | ||
| 21777 | 3 | break; | |
| 21778 | } | ||
| 21779 | |||
| 21780 | /* Success */ | ||
| 21781 | 3 | return (false); | |
| 21782 | } | ||
| 21783 | |||
| 21784 | /** Handling the shared INNOBASE_SHARE structure that is needed to provide table | ||
| 21785 | locking. Register the table name if it doesn't exist in the hash table. */ | ||
| 21786 | 4025396 | static INNOBASE_SHARE *get_share(const char *table_name) { | |
| 21787 | INNOBASE_SHARE *share; | ||
| 21788 | |||
| 21789 | 4025396 | mysql_mutex_lock(&innobase_share_mutex); | |
| 21790 | |||
| 21791 | 4025396 | const auto hash_value = ut::hash_string(table_name); | |
| 21792 | |||
| 21793 |
5/6✗ Branch 0 not taken.
✓ Branch 1 taken 2452267 times.
✓ Branch 2 taken 2181479 times.
✓ Branch 3 taken 270788 times.
✓ Branch 4 taken 2452267 times.
✓ Branch 5 taken 1843917 times.
|
4296184 | HASH_SEARCH(table_name_hash, innobase_open_tables, hash_value, |
| 21794 | INNOBASE_SHARE *, share, ut_ad(share->use_count > 0), | ||
| 21795 | !strcmp(share->table_name, table_name)); | ||
| 21796 | |||
| 21797 |
2/2✓ Branch 0 taken 1843917 times.
✓ Branch 1 taken 2181479 times.
|
4025396 | if (share == nullptr) { |
| 21798 | 1843917 | uint length = (uint)strlen(table_name); | |
| 21799 | |||
| 21800 | /* TODO: invoke HASH_MIGRATE if innobase_open_tables | ||
| 21801 | grows too big */ | ||
| 21802 | |||
| 21803 | share = reinterpret_cast<INNOBASE_SHARE *>( | ||
| 21804 | 1843917 | my_malloc(PSI_INSTRUMENT_ME, sizeof(*share) + length + 1, | |
| 21805 | MYF(MY_FAE | MY_ZEROFILL))); | ||
| 21806 | |||
| 21807 | 1843917 | share->table_name = | |
| 21808 | 1843917 | reinterpret_cast<char *>(memcpy(share + 1, table_name, length + 1)); | |
| 21809 | |||
| 21810 |
4/4✓ Branch 0 taken 1720334 times.
✓ Branch 1 taken 123583 times.
✓ Branch 2 taken 17526 times.
✓ Branch 3 taken 123583 times.
|
1861443 | HASH_INSERT(INNOBASE_SHARE, table_name_hash, innobase_open_tables, |
| 21811 | hash_value, share); | ||
| 21812 | |||
| 21813 | /* Index translation table initialization */ | ||
| 21814 | 1843917 | share->idx_trans_tbl.index_mapping = nullptr; | |
| 21815 | 1843917 | share->idx_trans_tbl.index_count = 0; | |
| 21816 | 1843917 | share->idx_trans_tbl.array_size = 0; | |
| 21817 | } | ||
| 21818 | |||
| 21819 | 4025396 | ++share->use_count; | |
| 21820 | |||
| 21821 | 4025396 | mysql_mutex_unlock(&innobase_share_mutex); | |
| 21822 | |||
| 21823 | 4025396 | return (share); | |
| 21824 | } | ||
| 21825 | |||
| 21826 | /** Free the shared object that was registered with get_share(). */ | ||
| 21827 | 3917077 | static void free_share( | |
| 21828 | INNOBASE_SHARE *share) /*!< in/own: table share to free */ | ||
| 21829 | { | ||
| 21830 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3917077 times.
|
3917077 | if (!share) { |
| 21831 | ✗ | return; | |
| 21832 | } | ||
| 21833 | |||
| 21834 | 3917077 | mysql_mutex_lock(&innobase_share_mutex); | |
| 21835 | |||
| 21836 | #ifdef UNIV_DEBUG | ||
| 21837 | INNOBASE_SHARE *share2; | ||
| 21838 | 3917082 | const auto hash_value = ut::hash_string(share->table_name); | |
| 21839 | |||
| 21840 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 4111793 times.
✓ Branch 2 taken 3917082 times.
✓ Branch 3 taken 194711 times.
✓ Branch 4 taken 4111793 times.
✗ Branch 5 not taken.
|
4111793 | HASH_SEARCH(table_name_hash, innobase_open_tables, hash_value, |
| 21841 | INNOBASE_SHARE *, share2, ut_ad(share->use_count > 0), | ||
| 21842 | !strcmp(share->table_name, share2->table_name)); | ||
| 21843 | |||
| 21844 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3917082 times.
|
3917082 | ut_a(share2 == share); |
| 21845 | #endif /* UNIV_DEBUG */ | ||
| 21846 | |||
| 21847 | 3917082 | --share->use_count; | |
| 21848 | |||
| 21849 |
2/2✓ Branch 0 taken 1788137 times.
✓ Branch 1 taken 2128945 times.
|
3917082 | if (share->use_count == 0) { |
| 21850 | 1788137 | const auto hash_value = ut::hash_string(share->table_name); | |
| 21851 | |||
| 21852 |
5/6✓ Branch 0 taken 1709372 times.
✓ Branch 1 taken 78765 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3484 times.
✓ Branch 4 taken 3484 times.
✓ Branch 5 taken 78765 times.
|
1791621 | HASH_DELETE(INNOBASE_SHARE, table_name_hash, innobase_open_tables, |
| 21853 | hash_value, share); | ||
| 21854 | |||
| 21855 | /* Free any memory from index translation table */ | ||
| 21856 | 1788137 | ut::free(share->idx_trans_tbl.index_mapping); | |
| 21857 | |||
| 21858 | 1788137 | my_free(share); | |
| 21859 | |||
| 21860 | /* TODO: invoke HASH_MIGRATE if innobase_open_tables | ||
| 21861 | shrinks too much */ | ||
| 21862 | } | ||
| 21863 | |||
| 21864 | 3917082 | mysql_mutex_unlock(&innobase_share_mutex); | |
| 21865 | } | ||
| 21866 | |||
| 21867 | /** Returns number of THR_LOCK locks used for one instance of InnoDB table. | ||
| 21868 | InnoDB no longer relies on THR_LOCK locks so 0 value is returned. | ||
| 21869 | Instead of THR_LOCK locks InnoDB relies on combination of metadata locks | ||
| 21870 | (e.g. for LOCK TABLES and DDL) and its own locking subsystem. | ||
| 21871 | Note that even though this method returns 0, SQL-layer still calls | ||
| 21872 | "::store_lock()", "::start_stmt()" and "::external_lock()" methods for InnoDB | ||
| 21873 | tables. */ | ||
| 21874 | |||
| 21875 | 105042241 | uint ha_innobase::lock_count(void) const { return 0; } | |
| 21876 | |||
| 21877 | /** Supposed to convert a MySQL table lock stored in the 'lock' field of the | ||
| 21878 | handle to a proper type before storing pointer to the lock into an array | ||
| 21879 | of pointers. | ||
| 21880 | In practice, since InnoDB no longer relies on THR_LOCK locks and its | ||
| 21881 | lock_count() method returns 0 it just informs storage engine about type | ||
| 21882 | of THR_LOCK which SQL-layer would have acquired for this specific statement | ||
| 21883 | on this specific table. | ||
| 21884 | MySQL also calls this if it wants to reset some table locks to a not-locked | ||
| 21885 | state during the processing of an SQL query. An example is that during a | ||
| 21886 | SELECT the read lock is released early on the 'const' tables where we only | ||
| 21887 | fetch one row. MySQL does not call this when it releases all locks at the | ||
| 21888 | end of an SQL statement. | ||
| 21889 | @return pointer to the current element in the 'to' array. */ | ||
| 21890 | |||
| 21891 | 105042564 | THR_LOCK_DATA **ha_innobase::store_lock( | |
| 21892 | THD *thd, /*!< in: user thread handle */ | ||
| 21893 | THR_LOCK_DATA **to, /*!< in: pointer to the current | ||
| 21894 | element in an array of pointers | ||
| 21895 | to lock structs; | ||
| 21896 | only used as return value */ | ||
| 21897 | thr_lock_type lock_type) /*!< in: lock type to store in | ||
| 21898 | 'lock'; this may also be | ||
| 21899 | TL_IGNORE */ | ||
| 21900 | { | ||
| 21901 | /* Note that trx in this function is NOT necessarily m_prebuilt->trx | ||
| 21902 | because we call update_thd() later, in ::external_lock()! Failure to | ||
| 21903 | understand this caused a serious memory corruption bug in 5.1.11. */ | ||
| 21904 | |||
| 21905 |
1/2✓ Branch 0 taken 105043745 times.
✗ Branch 1 not taken.
|
105042564 | trx_t *trx = check_trx_exists(thd); |
| 21906 | |||
| 21907 |
1/2✓ Branch 0 taken 105043479 times.
✗ Branch 1 not taken.
|
105043745 | TrxInInnoDB trx_in_innodb(trx); |
| 21908 | |||
| 21909 | /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE! | ||
| 21910 | Be careful to ignore TL_IGNORE if we are going to do something with | ||
| 21911 | only 'real' locks! */ | ||
| 21912 | |||
| 21913 | /* If no MySQL table is in use, we need to set the isolation level | ||
| 21914 | of the transaction. */ | ||
| 21915 | |||
| 21916 |
4/4✓ Branch 0 taken 104933873 times.
✓ Branch 1 taken 109606 times.
✓ Branch 2 taken 104456209 times.
✓ Branch 3 taken 477664 times.
|
105043479 | if (lock_type != TL_IGNORE && trx->n_mysql_tables_in_use == 0) { |
| 21917 | 104455557 | trx->isolation_level = | |
| 21918 |
2/4✓ Branch 0 taken 104455136 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104455557 times.
✗ Branch 3 not taken.
|
104456209 | innobase_trx_map_isolation_level(thd_get_trx_isolation(thd)); |
| 21919 | |||
| 21920 |
4/4✓ Branch 0 taken 74901830 times.
✓ Branch 1 taken 29553727 times.
✓ Branch 2 taken 506 times.
✓ Branch 3 taken 104455001 times.
|
179357337 | if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && |
| 21921 |
3/4✓ Branch 0 taken 74901780 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 506 times.
✓ Branch 3 taken 74901274 times.
|
74901830 | MVCC::is_view_active(trx->read_view)) { |
| 21922 | /* At low transaction isolation levels we let | ||
| 21923 | each consistent read set its own snapshot */ | ||
| 21924 | |||
| 21925 |
1/2✓ Branch 0 taken 506 times.
✗ Branch 1 not taken.
|
506 | mutex_enter(&trx_sys->mutex); |
| 21926 | |||
| 21927 |
1/2✓ Branch 0 taken 506 times.
✗ Branch 1 not taken.
|
506 | trx_sys->mvcc->view_close(trx->read_view, true); |
| 21928 | |||
| 21929 |
1/2✓ Branch 0 taken 506 times.
✗ Branch 1 not taken.
|
506 | mutex_exit(&trx_sys->mutex); |
| 21930 | } | ||
| 21931 | } | ||
| 21932 | |||
| 21933 |
2/4✓ Branch 0 taken 105043174 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 105043174 times.
|
105042777 | assert(EQ_CURRENT_THD(thd)); |
| 21934 |
1/2✓ Branch 0 taken 105042766 times.
✗ Branch 1 not taken.
|
105043174 | const bool in_lock_tables = thd_in_lock_tables(thd); |
| 21935 |
1/2✓ Branch 0 taken 105043136 times.
✗ Branch 1 not taken.
|
105042766 | const uint sql_command = thd_sql_command(thd); |
| 21936 | |||
| 21937 |
8/10✓ Branch 0 taken 74064 times.
✓ Branch 1 taken 104969072 times.
✓ Branch 2 taken 74064 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 74064 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 73754 times.
✓ Branch 7 taken 310 times.
✓ Branch 8 taken 940 times.
✓ Branch 9 taken 105042196 times.
|
105116890 | if (srv_read_only_mode && !m_prebuilt->table->is_intrinsic() && |
| 21938 |
4/4✓ Branch 0 taken 73435 times.
✓ Branch 1 taken 319 times.
✓ Branch 2 taken 73434 times.
✓ Branch 3 taken 1 times.
|
73754 | (sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_INSERT || |
| 21939 |
2/4✓ Branch 0 taken 73434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73434 times.
✗ Branch 3 not taken.
|
73434 | sql_command == SQLCOM_REPLACE || sql_command == SQLCOM_DROP_TABLE || |
| 21940 |
2/4✓ Branch 0 taken 73434 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 73434 times.
|
73434 | sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE || |
| 21941 | ✗ | (sql_command == SQLCOM_CREATE_TABLE && | |
| 21942 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 73434 times.
✗ Branch 3 not taken.
|
73434 | (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE)) || |
| 21943 |
3/4✓ Branch 0 taken 73434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73131 times.
✓ Branch 3 taken 303 times.
|
73434 | sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_DROP_INDEX || |
| 21944 |
2/2✓ Branch 0 taken 73128 times.
✓ Branch 1 taken 3 times.
|
73131 | sql_command == SQLCOM_DELETE || |
| 21945 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 73124 times.
|
73128 | sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY || |
| 21946 | sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) { | ||
| 21947 |
1/2✓ Branch 0 taken 940 times.
✗ Branch 1 not taken.
|
940 | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 21948 | |||
| 21949 |
4/4✓ Branch 0 taken 91355 times.
✓ Branch 1 taken 104950841 times.
✓ Branch 2 taken 405 times.
✓ Branch 3 taken 90950 times.
|
105042196 | } else if (sql_command == SQLCOM_FLUSH && lock_type == TL_READ_NO_INSERT) { |
| 21950 | /* Check for FLUSH TABLES ... WITH READ LOCK */ | ||
| 21951 | |||
| 21952 | /* Note: This call can fail, but there is no way to return | ||
| 21953 | the error to the caller. We simply ignore it for now here | ||
| 21954 | and push the error code to the caller where the error is | ||
| 21955 | detected in the function. */ | ||
| 21956 | |||
| 21957 |
1/2✓ Branch 0 taken 405 times.
✗ Branch 1 not taken.
|
405 | dberr_t err = row_quiesce_set_state(m_prebuilt->table, QUIESCE_START, trx); |
| 21958 | |||
| 21959 |
4/6✓ Branch 0 taken 8 times.
✓ Branch 1 taken 397 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 405 times.
|
405 | ut_a(err == DB_SUCCESS || err == DB_UNSUPPORTED); |
| 21960 | |||
| 21961 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 403 times.
|
405 | if (trx->isolation_level == TRX_ISO_SERIALIZABLE) { |
| 21962 | 2 | m_prebuilt->select_lock_type = LOCK_S; | |
| 21963 | 2 | m_stored_select_lock_type = LOCK_S; | |
| 21964 | } else { | ||
| 21965 | 403 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 21966 | 403 | m_stored_select_lock_type = LOCK_NONE; | |
| 21967 | } | ||
| 21968 | |||
| 21969 | /* Check for DROP TABLE */ | ||
| 21970 |
2/2✓ Branch 0 taken 105040892 times.
✓ Branch 1 taken 899 times.
|
105042196 | } else if (sql_command == SQLCOM_DROP_TABLE) { |
| 21971 | /* MySQL calls this function in DROP TABLE though this table | ||
| 21972 | handle may belong to another thd that is running a query. Let | ||
| 21973 | us in that case skip any changes to the m_prebuilt struct. */ | ||
| 21974 | |||
| 21975 | /* Check for LOCK TABLE t1,...,tn WITH SHARED LOCKS */ | ||
| 21976 |
6/6✓ Branch 0 taken 78624728 times.
✓ Branch 1 taken 26416164 times.
✓ Branch 2 taken 78622290 times.
✓ Branch 3 taken 2438 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 105038434 times.
|
105040892 | } else if ((lock_type == TL_READ && in_lock_tables) || |
| 21977 |
3/4✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105037908 times.
✓ Branch 3 taken 546 times.
|
105038454 | (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables) || |
| 21978 |
2/2✓ Branch 0 taken 104916950 times.
✓ Branch 1 taken 120958 times.
|
105037908 | lock_type == TL_READ_WITH_SHARED_LOCKS || |
| 21979 |
2/2✓ Branch 0 taken 104807707 times.
✓ Branch 1 taken 109243 times.
|
104916950 | lock_type == TL_READ_NO_INSERT || |
| 21980 |
2/2✓ Branch 0 taken 28004265 times.
✓ Branch 1 taken 76803442 times.
|
104807707 | (lock_type != TL_IGNORE && sql_command != SQLCOM_SELECT)) { |
| 21981 | /* The OR cases above are in this order: | ||
| 21982 | 1) MySQL is doing LOCK TABLES ... READ LOCAL, or we | ||
| 21983 | are processing a stored procedure or function, or | ||
| 21984 | 2) (we do not know when TL_READ_HIGH_PRIORITY is used), or | ||
| 21985 | 3) this is a SELECT ... IN SHARE MODE/FOR SHARE, or | ||
| 21986 | 4) we are doing a complex SQL statement like | ||
| 21987 | INSERT INTO ... SELECT ... and the logical logging (MySQL | ||
| 21988 | binlog) requires the use of a locking read, or | ||
| 21989 | MySQL is doing LOCK TABLES ... READ. | ||
| 21990 | 5) we let InnoDB do locking reads for all SQL statements that | ||
| 21991 | are not simple SELECTs; note that select_lock_type in this | ||
| 21992 | case may get strengthened in ::external_lock() to LOCK_X. | ||
| 21993 | Note that we MUST use a locking read in all data modifying | ||
| 21994 | SQL statements, because otherwise the execution would not be | ||
| 21995 | serializable, and also the results from the update could be | ||
| 21996 | unexpected if an obsolete consistent read view would be | ||
| 21997 | used. */ | ||
| 21998 | |||
| 21999 | /* Use consistent read for checksum table */ | ||
| 22000 | |||
| 22001 |
4/4✓ Branch 0 taken 27531373 times.
✓ Branch 1 taken 596834 times.
✓ Branch 2 taken 597074 times.
✓ Branch 3 taken 27531059 times.
|
55659506 | if (sql_command == SQLCOM_CHECKSUM || |
| 22002 |
5/6✓ Branch 0 taken 27531299 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 580037 times.
✓ Branch 3 taken 26951262 times.
✓ Branch 4 taken 572441 times.
✓ Branch 5 taken 7596 times.
|
27531373 | (trx->skip_gap_locks() && |
| 22003 |
4/4✓ Branch 0 taken 1016 times.
✓ Branch 1 taken 571425 times.
✓ Branch 2 taken 8554 times.
✓ Branch 3 taken 58 times.
|
580037 | (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) && |
| 22004 |
2/2✓ Branch 0 taken 8550 times.
✓ Branch 1 taken 4 times.
|
8554 | (sql_command == SQLCOM_INSERT_SELECT || |
| 22005 |
2/2✓ Branch 0 taken 8489 times.
✓ Branch 1 taken 61 times.
|
8550 | sql_command == SQLCOM_REPLACE_SELECT || |
| 22006 |
2/2✓ Branch 0 taken 117 times.
✓ Branch 1 taken 8372 times.
|
8489 | sql_command == SQLCOM_UPDATE || |
| 22007 | sql_command == SQLCOM_CREATE_TABLE))) { | ||
| 22008 | /* If this session is using READ COMMITTED or READ | ||
| 22009 | UNCOMMITTED isolation level and MySQL is doing INSERT | ||
| 22010 | INTO... SELECT or REPLACE INTO...SELECT or UPDATE ... | ||
| 22011 | = (SELECT ...) or CREATE ... SELECT... without FOR | ||
| 22012 | UPDATE or IN SHARE MODE in select, then we use | ||
| 22013 | consistent read for select. | ||
| 22014 | |||
| 22015 | See also similar code in ha_innobase::start_stmt(). */ | ||
| 22016 | |||
| 22017 | 597074 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 22018 | 597074 | m_stored_select_lock_type = LOCK_NONE; | |
| 22019 | } else { | ||
| 22020 | 27531059 | m_prebuilt->select_lock_type = LOCK_S; | |
| 22021 | 27531059 | m_stored_select_lock_type = LOCK_S; | |
| 22022 | } | ||
| 22023 | |||
| 22024 |
2/2✓ Branch 0 taken 76803826 times.
✓ Branch 1 taken 108859 times.
|
76912685 | } else if (lock_type != TL_IGNORE) { |
| 22025 | /* We set possible LOCK_X value in external_lock, not yet | ||
| 22026 | here even if this would be SELECT ... FOR UPDATE */ | ||
| 22027 | |||
| 22028 | 76803826 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 22029 | 76803826 | m_stored_select_lock_type = LOCK_NONE; | |
| 22030 | } | ||
| 22031 | |||
| 22032 | /* Set select mode for SKIP LOCKED / NOWAIT */ | ||
| 22033 |
2/2✓ Branch 0 taken 104933123 times.
✓ Branch 1 taken 109939 times.
|
105043062 | if (lock_type != TL_IGNORE) { |
| 22034 |
3/3✓ Branch 0 taken 100 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 104933245 times.
|
104933123 | switch (table->pos_in_table_list->lock_descriptor().action) { |
| 22035 | 100 | case THR_SKIP: | |
| 22036 | 100 | m_prebuilt->select_mode = SELECT_SKIP_LOCKED; | |
| 22037 | 100 | break; | |
| 22038 | 96 | case THR_NOWAIT: | |
| 22039 | 96 | m_prebuilt->select_mode = SELECT_NOWAIT; | |
| 22040 | 96 | break; | |
| 22041 | 104933245 | default: | |
| 22042 | 104933245 | m_prebuilt->select_mode = SELECT_ORDINARY; | |
| 22043 | 104933245 | break; | |
| 22044 | } | ||
| 22045 | } | ||
| 22046 | |||
| 22047 | /* Ignore SKIP LOCKED / NO_WAIT for high priority transaction */ | ||
| 22048 |
3/4✓ Branch 0 taken 105042438 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1231996 times.
✓ Branch 3 taken 103810442 times.
|
105043380 | if (trx_is_high_priority(trx)) { |
| 22049 | 1231996 | m_prebuilt->select_mode = SELECT_ORDINARY; | |
| 22050 | } | ||
| 22051 | |||
| 22052 |
7/8✓ Branch 0 taken 105042112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87455648 times.
✓ Branch 3 taken 17586464 times.
✓ Branch 4 taken 77393847 times.
✓ Branch 5 taken 10061801 times.
✓ Branch 6 taken 10062696 times.
✓ Branch 7 taken 94979416 times.
|
182436285 | if (!trx_is_started(trx) && (m_prebuilt->select_lock_type != LOCK_NONE || |
| 22053 |
2/2✓ Branch 0 taken 848 times.
✓ Branch 1 taken 77392999 times.
|
77393847 | m_stored_select_lock_type != LOCK_NONE)) { |
| 22054 | 10062696 | ++trx->will_lock; | |
| 22055 | } | ||
| 22056 | |||
| 22057 | #ifdef UNIV_DEBUG | ||
| 22058 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 105042112 times.
|
105042112 | if (trx->is_dd_trx) { |
| 22059 | ✗ | ut_ad(trx->will_lock == 0 && m_prebuilt->select_lock_type == LOCK_NONE); | |
| 22060 | } | ||
| 22061 | #endif /* UNIV_DEBUG */ | ||
| 22062 | |||
| 22063 | 105043596 | return (to); | |
| 22064 | 105042112 | } | |
| 22065 | |||
| 22066 | /** Read the next autoinc value. Acquire the relevant locks before reading | ||
| 22067 | the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked | ||
| 22068 | on return and all relevant locks acquired. | ||
| 22069 | @return DB_SUCCESS or error code */ | ||
| 22070 | |||
| 22071 | 7057510 | dberr_t ha_innobase::innobase_get_autoinc( | |
| 22072 | ulonglong *value) /*!< out: autoinc value */ | ||
| 22073 | { | ||
| 22074 | 7057510 | *value = 0; | |
| 22075 | |||
| 22076 | 7057510 | m_prebuilt->autoinc_error = innobase_lock_autoinc(); | |
| 22077 | |||
| 22078 |
1/2✓ Branch 0 taken 7057671 times.
✗ Branch 1 not taken.
|
7057668 | if (m_prebuilt->autoinc_error == DB_SUCCESS) { |
| 22079 | /* Determine the first value of the interval */ | ||
| 22080 | 7057671 | *value = dict_table_autoinc_read(m_prebuilt->table); | |
| 22081 | |||
| 22082 | /* It should have been initialized during open. */ | ||
| 22083 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7057632 times.
|
7057632 | if (*value == 0) { |
| 22084 | ✗ | m_prebuilt->autoinc_error = DB_UNSUPPORTED; | |
| 22085 | ✗ | dict_table_autoinc_unlock(m_prebuilt->table); | |
| 22086 | } | ||
| 22087 | } | ||
| 22088 | |||
| 22089 | 7057647 | return (m_prebuilt->autoinc_error); | |
| 22090 | } | ||
| 22091 | |||
| 22092 | 17644004 | void ha_innobase::release_auto_increment() { | |
| 22093 | 17644004 | trx_t *trx = m_prebuilt->trx; | |
| 22094 |
1/2✓ Branch 0 taken 17644036 times.
✗ Branch 1 not taken.
|
17644004 | TrxInInnoDB trx_in_innodb(trx); |
| 22095 | |||
| 22096 | /* Clear the trx's autoinc_rows as the operation requiring auto increment | ||
| 22097 | values has been completed. | ||
| 22098 | |||
| 22099 | We usually end up in this scenario when we do not know the correct estimation | ||
| 22100 | of rows in the table in the case of bulk inserts. */ | ||
| 22101 |
2/2✓ Branch 0 taken 12521 times.
✓ Branch 1 taken 17631515 times.
|
17644036 | if (trx->n_autoinc_rows > 0) { |
| 22102 | 12521 | trx->n_autoinc_rows = 0; | |
| 22103 | } | ||
| 22104 | 17644036 | } | |
| 22105 | |||
| 22106 | /** Returns the value of the auto-inc counter in *first_value and ~0 on failure. | ||
| 22107 | */ | ||
| 22108 | |||
| 22109 | 7057386 | void ha_innobase::get_auto_increment( | |
| 22110 | ulonglong offset, /*!< in: table autoinc offset */ | ||
| 22111 | ulonglong increment, /*!< in: table autoinc | ||
| 22112 | increment */ | ||
| 22113 | ulonglong nb_desired_values, /*!< in: number of values | ||
| 22114 | reqd */ | ||
| 22115 | ulonglong *first_value, /*!< out: the autoinc value */ | ||
| 22116 | ulonglong *nb_reserved_values) /*!< out: count of reserved | ||
| 22117 | values */ | ||
| 22118 | { | ||
| 22119 | trx_t *trx; | ||
| 22120 | dberr_t error; | ||
| 22121 | 7057386 | ulonglong autoinc = 0; | |
| 22122 | |||
| 22123 | /* Prepare m_prebuilt->trx in the table handle */ | ||
| 22124 |
2/4✓ Branch 0 taken 7057624 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7057675 times.
✗ Branch 3 not taken.
|
7057386 | update_thd(ha_thd()); |
| 22125 | |||
| 22126 |
1/2✓ Branch 0 taken 7057651 times.
✗ Branch 1 not taken.
|
7057675 | error = innobase_get_autoinc(&autoinc); |
| 22127 | |||
| 22128 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7057650 times.
|
7057651 | if (error != DB_SUCCESS) { |
| 22129 | 1 | *first_value = (~(ulonglong)0); | |
| 22130 | 1 | return; | |
| 22131 | } | ||
| 22132 | |||
| 22133 | /* This is a hack, since nb_desired_values seems to be accurate only | ||
| 22134 | for the first call to get_auto_increment() for multi-row INSERT and | ||
| 22135 | meaningless for other statements e.g, LOAD etc. Subsequent calls to | ||
| 22136 | this method for the same statement results in different values which | ||
| 22137 | don't make sense. Therefore we store the value the first time we are | ||
| 22138 | called and count down from that as rows are written (see write_row()). | ||
| 22139 | */ | ||
| 22140 | |||
| 22141 | 7057650 | trx = m_prebuilt->trx; | |
| 22142 | |||
| 22143 |
1/2✓ Branch 0 taken 7057660 times.
✗ Branch 1 not taken.
|
7057650 | TrxInInnoDB trx_in_innodb(trx); |
| 22144 | |||
| 22145 | /* Note: We can't rely on *first_value since some MySQL engines, | ||
| 22146 | in particular the partition engine, don't initialize it to 0 when | ||
| 22147 | invoking this method. So we are not sure if it's guaranteed to | ||
| 22148 | be 0 or not. */ | ||
| 22149 | |||
| 22150 | /* We need the upper limit of the col type to check for | ||
| 22151 | whether we update the table autoinc counter or not. */ | ||
| 22152 |
1/2✓ Branch 0 taken 7057672 times.
✗ Branch 1 not taken.
|
7057660 | ulonglong col_max_value = table->next_number_field->get_max_int_value(); |
| 22153 | |||
| 22154 | /** The following logic is needed to avoid duplicate key error | ||
| 22155 | for autoincrement column. | ||
| 22156 | |||
| 22157 | (1) InnoDB gives the current autoincrement value with respect | ||
| 22158 | to increment and offset value. | ||
| 22159 | |||
| 22160 | (2) Basically it does compute_next_insert_id() logic inside InnoDB | ||
| 22161 | to avoid the current auto increment value changed by handler layer. | ||
| 22162 | |||
| 22163 | (3) It is restricted only for insert operations. */ | ||
| 22164 | |||
| 22165 |
4/4✓ Branch 0 taken 15558 times.
✓ Branch 1 taken 7042114 times.
✓ Branch 2 taken 15556 times.
✓ Branch 3 taken 2 times.
|
7057672 | if (increment > 1 && m_prebuilt->table->skip_alter_undo == false && |
| 22166 |
2/2✓ Branch 0 taken 15547 times.
✓ Branch 1 taken 9 times.
|
15556 | autoinc < col_max_value) { |
| 22167 | 15547 | ulonglong diff = ULLONG_MAX - autoinc; | |
| 22168 | /* Check for overflow */ | ||
| 22169 |
2/2✓ Branch 0 taken 15545 times.
✓ Branch 1 taken 2 times.
|
15547 | if (increment <= diff) { |
| 22170 | 15545 | ulonglong prev_auto_inc = autoinc; | |
| 22171 | 15545 | autoinc = ((autoinc - 1) + increment - offset) / increment; | |
| 22172 | 15545 | autoinc = autoinc * increment + offset; | |
| 22173 | |||
| 22174 | /* If autoinc exceeds the col_max_value then reset | ||
| 22175 | to old autoinc value. Because in case of non-strict | ||
| 22176 | sql mode, boundary value is not considered as error. */ | ||
| 22177 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 15544 times.
|
15545 | if (autoinc >= col_max_value) { |
| 22178 | 1 | autoinc = prev_auto_inc; | |
| 22179 | } | ||
| 22180 | |||
| 22181 |
2/2✓ Branch 0 taken 63 times.
✓ Branch 1 taken 15482 times.
|
15545 | ut_ad(autoinc > 0); |
| 22182 | } | ||
| 22183 | } | ||
| 22184 | |||
| 22185 | /* Called for the first time ? */ | ||
| 22186 |
2/2✓ Branch 0 taken 7057534 times.
✓ Branch 1 taken 75 times.
|
7057609 | if (trx->n_autoinc_rows == 0) { |
| 22187 | 7057534 | trx->n_autoinc_rows = (ulint)nb_desired_values; | |
| 22188 | |||
| 22189 | /* It's possible for nb_desired_values to be 0: | ||
| 22190 | e.g., INSERT INTO T1(C) SELECT C FROM T2; */ | ||
| 22191 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7057534 times.
|
7057534 | if (nb_desired_values == 0) { |
| 22192 | ✗ | trx->n_autoinc_rows = 1; | |
| 22193 | } | ||
| 22194 | |||
| 22195 | 7057534 | *first_value = std::max(*first_value, autoinc); | |
| 22196 | /* Not in the middle of a mult-row INSERT. */ | ||
| 22197 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 57 times.
|
75 | } else if (m_prebuilt->autoinc_last_value == 0) { |
| 22198 | 18 | *first_value = std::max(*first_value, autoinc); | |
| 22199 | /* Check for -ve values. */ | ||
| 22200 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
57 | } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) { |
| 22201 | /* Set to next logical value. */ | ||
| 22202 | ✗ | ut_a(autoinc > trx->n_autoinc_rows); | |
| 22203 | ✗ | *first_value = (autoinc - trx->n_autoinc_rows) - 1; | |
| 22204 | } | ||
| 22205 | |||
| 22206 | 7057580 | *nb_reserved_values = trx->n_autoinc_rows; | |
| 22207 | |||
| 22208 | /* With old style AUTOINC locking we only update the table's | ||
| 22209 | AUTOINC counter after attempting to insert the row. */ | ||
| 22210 |
2/2✓ Branch 0 taken 9500 times.
✓ Branch 1 taken 7048080 times.
|
7057580 | if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING || |
| 22211 |
2/2✓ Branch 0 taken 6567 times.
✓ Branch 1 taken 2933 times.
|
9500 | m_prebuilt->no_autoinc_locking) { |
| 22212 | ulonglong current; | ||
| 22213 | ulonglong next_value; | ||
| 22214 | |||
| 22215 |
2/2✓ Branch 0 taken 7054618 times.
✓ Branch 1 taken 29 times.
|
7054647 | current = *first_value > col_max_value ? autoinc : *first_value; |
| 22216 | |||
| 22217 | #if 0 | ||
| 22218 | /* If the increment step of the auto increment column | ||
| 22219 | decreases then it is not affecting the immediate | ||
| 22220 | next value in the series. */ | ||
| 22221 | if (m_prebuilt->autoinc_increment > increment) { | ||
| 22222 | #ifdef WITH_WSREP | ||
| 22223 | WSREP_DEBUG( | ||
| 22224 | "Refresh change in auto-inc configuration" | ||
| 22225 | " from (off: %llu -> %llu)" | ||
| 22226 | " and (inc: %llu -> %llu)." | ||
| 22227 | " Re-align auto increment" | ||
| 22228 | " value for table (%s)" | ||
| 22229 | " THD: %u, current: %llu, autoinc: %llu", | ||
| 22230 | m_prebuilt->autoinc_offset, offset, m_prebuilt->autoinc_increment, | ||
| 22231 | increment, m_prebuilt->table->name.m_name, | ||
| 22232 | wsrep_thd_thread_id(ha_thd()), current, autoinc); | ||
| 22233 | /* MySQL flow will construct last_inserted_id but PXC | ||
| 22234 | can't do so because any values in that range are | ||
| 22235 | potentially unsafe as they were reserved for other node | ||
| 22236 | and if other node has used them it will result in | ||
| 22237 | conflict. So PXC skip this readjustment logic | ||
| 22238 | and re-calibration too as there is no change in | ||
| 22239 | current autoinc value. */ | ||
| 22240 | if (!wsrep_on(ha_thd())) { | ||
| 22241 | current = autoinc - m_prebuilt->autoinc_increment; | ||
| 22242 | |||
| 22243 | current = | ||
| 22244 | innobase_next_autoinc(current, 1, increment, 1, col_max_value); | ||
| 22245 | } | ||
| 22246 | #else | ||
| 22247 | current = autoinc - m_prebuilt->autoinc_increment; | ||
| 22248 | |||
| 22249 | current = innobase_next_autoinc(current, 1, increment, 1, col_max_value); | ||
| 22250 | #endif /* WITH_WSREP */ | ||
| 22251 | |||
| 22252 | dict_table_autoinc_initialize(m_prebuilt->table, current); | ||
| 22253 | |||
| 22254 | *first_value = current; | ||
| 22255 | } | ||
| 22256 | #endif | ||
| 22257 | |||
| 22258 | /* Compute the last value in the interval */ | ||
| 22259 |
1/2✓ Branch 0 taken 7054724 times.
✗ Branch 1 not taken.
|
7054647 | next_value = innobase_next_autoinc(current, *nb_reserved_values, increment, |
| 22260 | offset, col_max_value); | ||
| 22261 | |||
| 22262 | 7054724 | m_prebuilt->autoinc_last_value = next_value; | |
| 22263 | |||
| 22264 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7054723 times.
|
7054724 | if (m_prebuilt->autoinc_last_value < *first_value) { |
| 22265 | 1 | *first_value = (~(ulonglong)0); | |
| 22266 | } else { | ||
| 22267 | /* Update the table autoinc variable */ | ||
| 22268 | 7054723 | dict_table_autoinc_update_if_greater(m_prebuilt->table, | |
| 22269 |
1/2✓ Branch 0 taken 7054711 times.
✗ Branch 1 not taken.
|
7054723 | m_prebuilt->autoinc_last_value); |
| 22270 | } | ||
| 22271 | 7054712 | } else { | |
| 22272 | /* This will force write_row() into attempting an update | ||
| 22273 | of the table's AUTOINC counter. */ | ||
| 22274 | 2933 | m_prebuilt->autoinc_last_value = 0; | |
| 22275 | } | ||
| 22276 | |||
| 22277 | /* The increment to be used to increase the AUTOINC value, we use | ||
| 22278 | this in write_row() and update_row() to increase the autoinc counter | ||
| 22279 | for columns that are filled by the user. We need the offset and | ||
| 22280 | the increment. */ | ||
| 22281 | 7057645 | m_prebuilt->autoinc_offset = offset; | |
| 22282 | 7057645 | m_prebuilt->autoinc_increment = increment; | |
| 22283 | |||
| 22284 |
1/2✓ Branch 0 taken 7057643 times.
✗ Branch 1 not taken.
|
7057645 | dict_table_autoinc_unlock(m_prebuilt->table); |
| 22285 | 7057643 | } | |
| 22286 | |||
| 22287 | /** See comment in handler.cc */ | ||
| 22288 | |||
| 22289 | 539 | bool ha_innobase::get_error_message(int error, String *buf) { | |
| 22290 | 539 | trx_t *trx = check_trx_exists(ha_thd()); | |
| 22291 | |||
| 22292 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 539 times.
|
539 | if (error == HA_ERR_ENCRYPTION_KEY_MISSING) { |
| 22293 | ✗ | const char *msg = | |
| 22294 | "Table encrypted but decryption key was not found. " | ||
| 22295 | "Is correct keyring loaded?"; | ||
| 22296 | ✗ | buf->copy(msg, (uint)strlen(msg), system_charset_info); | |
| 22297 | } else { | ||
| 22298 | 539 | buf->copy(trx->detailed_error, (uint)strlen(trx->detailed_error), | |
| 22299 | system_charset_info); | ||
| 22300 | } | ||
| 22301 | |||
| 22302 | 539 | return false; | |
| 22303 | } | ||
| 22304 | |||
| 22305 | /** Retrieves the names of the table and the key for which there was a | ||
| 22306 | duplicate entry in the case of HA_ERR_FOREIGN_DUPLICATE_KEY. | ||
| 22307 | |||
| 22308 | If any of the names is not available, then this method will return | ||
| 22309 | false and will not change any of child_table_name or child_key_name. | ||
| 22310 | |||
| 22311 | @param[out] child_table_name Table name | ||
| 22312 | @param[in] child_table_name_len Table name buffer size | ||
| 22313 | @param[out] child_key_name Key name | ||
| 22314 | @param[in] child_key_name_len Key name buffer size | ||
| 22315 | |||
| 22316 | @retval true table and key names were available and were written into the | ||
| 22317 | corresponding out parameters. | ||
| 22318 | @retval false table and key names were not available, the out parameters | ||
| 22319 | were not touched. */ | ||
| 22320 | 4 | bool ha_innobase::get_foreign_dup_key(char *child_table_name, | |
| 22321 | uint child_table_name_len, | ||
| 22322 | char *child_key_name, | ||
| 22323 | uint child_key_name_len) { | ||
| 22324 | const dict_index_t *err_index; | ||
| 22325 | |||
| 22326 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | ut_a(m_prebuilt->trx != nullptr); |
| 22327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 22328 | |||
| 22329 | 4 | err_index = trx_get_error_index(m_prebuilt->trx); | |
| 22330 | |||
| 22331 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (err_index == nullptr) { |
| 22332 | ✗ | return (false); | |
| 22333 | } | ||
| 22334 | /* else */ | ||
| 22335 | |||
| 22336 | /* copy table name (and convert from filename-safe encoding to | ||
| 22337 | system_charset_info) */ | ||
| 22338 | 4 | char *p = strchr(err_index->table->name.m_name, '/'); | |
| 22339 | |||
| 22340 | /* strip ".../" prefix if any */ | ||
| 22341 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (p != nullptr) { |
| 22342 | 4 | p++; | |
| 22343 | } else { | ||
| 22344 | ✗ | p = err_index->table->name.m_name; | |
| 22345 | } | ||
| 22346 | |||
| 22347 | size_t len; | ||
| 22348 | |||
| 22349 | 4 | len = filename_to_tablename(p, child_table_name, child_table_name_len); | |
| 22350 | |||
| 22351 | 4 | child_table_name[len] = '\0'; | |
| 22352 | |||
| 22353 | /* copy index name */ | ||
| 22354 | 4 | snprintf(child_key_name, child_key_name_len, "%s", err_index->name()); | |
| 22355 | |||
| 22356 | 4 | return (true); | |
| 22357 | } | ||
| 22358 | |||
| 22359 | /** Compares two 'refs'. A 'ref' is the (internal) primary key value of the row. | ||
| 22360 | If there is no explicitly declared non-null unique key or a primary key, then | ||
| 22361 | InnoDB internally uses the row id as the primary key. | ||
| 22362 | @return < 0 if ref1 < ref2, 0 if equal, else > 0 */ | ||
| 22363 | |||
| 22364 | 5410706 | int ha_innobase::cmp_ref( | |
| 22365 | const uchar *ref1, /*!< in: an (internal) primary key value in the | ||
| 22366 | MySQL key value format */ | ||
| 22367 | const uchar *ref2) /*!< in: an (internal) primary key value in the | ||
| 22368 | MySQL key value format */ | ||
| 22369 | const { | ||
| 22370 | enum_field_types mysql_type; | ||
| 22371 | Field *field; | ||
| 22372 | KEY_PART_INFO *key_part; | ||
| 22373 | KEY_PART_INFO *key_part_end; | ||
| 22374 | uint len1; | ||
| 22375 | uint len2; | ||
| 22376 | int result; | ||
| 22377 | |||
| 22378 |
2/2✓ Branch 0 taken 4236442 times.
✓ Branch 1 taken 1174264 times.
|
5410706 | if (m_prebuilt->clust_index_was_generated) { |
| 22379 | /* The 'ref' is an InnoDB row id */ | ||
| 22380 | |||
| 22381 | 4236442 | return (memcmp(ref1, ref2, DATA_ROW_ID_LEN)); | |
| 22382 | } | ||
| 22383 | |||
| 22384 | /* Do a type-aware comparison of primary key fields. PK fields | ||
| 22385 | are always NOT NULL, so no checks for NULL are performed. */ | ||
| 22386 | |||
| 22387 | 1174264 | key_part = table->key_info[table->s->primary_key].key_part; | |
| 22388 | |||
| 22389 | 1174264 | key_part_end = | |
| 22390 | 1174264 | key_part + table->key_info[table->s->primary_key].user_defined_key_parts; | |
| 22391 | |||
| 22392 |
2/2✓ Branch 0 taken 1174885 times.
✓ Branch 1 taken 121867 times.
|
1296752 | for (; key_part != key_part_end; ++key_part) { |
| 22393 | 1174885 | field = key_part->field; | |
| 22394 | 1174885 | mysql_type = field->type(); | |
| 22395 | |||
| 22396 |
2/4✓ Branch 0 taken 1174885 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1174885 times.
✗ Branch 3 not taken.
|
1174885 | if (mysql_type == MYSQL_TYPE_TINY_BLOB || |
| 22397 |
3/4✓ Branch 0 taken 1174842 times.
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1174842 times.
|
1174885 | mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB || |
| 22398 | mysql_type == MYSQL_TYPE_LONG_BLOB) { | ||
| 22399 | /* In the MySQL key value format, a column prefix of | ||
| 22400 | a BLOB is preceded by a 2-byte length field */ | ||
| 22401 | |||
| 22402 | 43 | len1 = innobase_read_from_2_little_endian(ref1); | |
| 22403 | 43 | len2 = innobase_read_from_2_little_endian(ref2); | |
| 22404 | |||
| 22405 | 43 | result = | |
| 22406 | 43 | down_cast<Field_blob *>(field)->cmp(ref1 + 2, len1, ref2 + 2, len2); | |
| 22407 | } else { | ||
| 22408 | 1174842 | result = field->key_cmp(ref1, ref2); | |
| 22409 | } | ||
| 22410 | |||
| 22411 |
2/2✓ Branch 0 taken 1052397 times.
✓ Branch 1 taken 122488 times.
|
1174885 | if (result) { |
| 22412 | 1052397 | return (result); | |
| 22413 | } | ||
| 22414 | |||
| 22415 | 122488 | ref1 += key_part->store_length; | |
| 22416 | 122488 | ref2 += key_part->store_length; | |
| 22417 | } | ||
| 22418 | |||
| 22419 | 121867 | return (0); | |
| 22420 | } | ||
| 22421 | |||
| 22422 | /** This function is used to find the storage length in bytes of the first n | ||
| 22423 | characters for prefix indexes using a multibyte character set. The function | ||
| 22424 | finds charset information and returns length of prefix_len characters in the | ||
| 22425 | index field in bytes. | ||
| 22426 | @return number of bytes occupied by the first n characters */ | ||
| 22427 | 95081 | ulint innobase_get_at_most_n_mbchars( | |
| 22428 | ulint charset_id, /*!< in: character set id */ | ||
| 22429 | ulint prefix_len, /*!< in: prefix length in bytes of the index | ||
| 22430 | (this has to be divided by mbmaxlen to get the | ||
| 22431 | number of CHARACTERS n in the prefix) */ | ||
| 22432 | ulint data_len, /*!< in: length of the string in bytes */ | ||
| 22433 | const char *str) /*!< in: character string */ | ||
| 22434 | { | ||
| 22435 | ulint char_length; /*!< character length in bytes */ | ||
| 22436 | ulint n_chars; /*!< number of characters in prefix */ | ||
| 22437 | CHARSET_INFO *charset; /*!< charset used in the field */ | ||
| 22438 | |||
| 22439 | 95081 | charset = get_charset((uint)charset_id, MYF(MY_WME)); | |
| 22440 | |||
| 22441 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 95083 times.
|
95082 | ut_ad(charset); |
| 22442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 95083 times.
|
95083 | ut_ad(charset->mbmaxlen); |
| 22443 | |||
| 22444 | /* Calculate how many characters at most the prefix index contains */ | ||
| 22445 | |||
| 22446 | 95083 | n_chars = prefix_len / charset->mbmaxlen; | |
| 22447 | |||
| 22448 | /* If the charset is multi-byte, then we must find the length of the | ||
| 22449 | first at most n chars in the string. If the string contains less | ||
| 22450 | characters than n, then we return the length to the end of the last | ||
| 22451 | character. */ | ||
| 22452 | |||
| 22453 |
1/2✓ Branch 0 taken 95083 times.
✗ Branch 1 not taken.
|
95083 | if (charset->mbmaxlen > 1) { |
| 22454 | /* my_charpos() returns the byte length of the first n_chars | ||
| 22455 | characters, or a value bigger than the length of str, if | ||
| 22456 | there were not enough full characters in str. | ||
| 22457 | |||
| 22458 | Why does the code below work: | ||
| 22459 | Suppose that we are looking for n UTF-8 characters. | ||
| 22460 | |||
| 22461 | 1) If the string is long enough, then the prefix contains at | ||
| 22462 | least n complete UTF-8 characters + maybe some extra | ||
| 22463 | characters + an incomplete UTF-8 character. No problem in | ||
| 22464 | this case. The function returns the pointer to the | ||
| 22465 | end of the nth character. | ||
| 22466 | |||
| 22467 | 2) If the string is not long enough, then the string contains | ||
| 22468 | the complete value of a column, that is, only complete UTF-8 | ||
| 22469 | characters, and we can store in the column prefix index the | ||
| 22470 | whole string. */ | ||
| 22471 | |||
| 22472 | 95083 | char_length = my_charpos(charset, str, str + data_len, (int)n_chars); | |
| 22473 |
2/2✓ Branch 0 taken 43494 times.
✓ Branch 1 taken 51603 times.
|
95097 | if (char_length > data_len) { |
| 22474 | 43494 | char_length = data_len; | |
| 22475 | } | ||
| 22476 | ✗ | } else if (data_len < prefix_len) { | |
| 22477 | ✗ | char_length = data_len; | |
| 22478 | |||
| 22479 | } else { | ||
| 22480 | ✗ | char_length = prefix_len; | |
| 22481 | } | ||
| 22482 | |||
| 22483 | 95097 | return (char_length); | |
| 22484 | } | ||
| 22485 | |||
| 22486 | /** This function is used to prepare an X/Open XA distributed transaction. | ||
| 22487 | @return 0 or error number */ | ||
| 22488 | 4973969 | static int innobase_xa_prepare(handlerton *hton, /*!< in: InnoDB handlerton */ | |
| 22489 | THD *thd, /*!< in: handle to the MySQL thread of | ||
| 22490 | the user whose XA transaction should | ||
| 22491 | be prepared */ | ||
| 22492 | bool prepare_trx) /*!< in: true - prepare | ||
| 22493 | transaction false - the current | ||
| 22494 | SQL statement ended */ | ||
| 22495 | { | ||
| 22496 |
1/2✓ Branch 0 taken 4974059 times.
✗ Branch 1 not taken.
|
4973969 | trx_t *trx = check_trx_exists(thd); |
| 22497 | |||
| 22498 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4974059 times.
|
4974059 | assert(hton == innodb_hton_ptr); |
| 22499 | |||
| 22500 |
1/2✓ Branch 0 taken 4973998 times.
✗ Branch 1 not taken.
|
4974059 | thd_get_xid(thd, (MYSQL_XID *)trx->xid); |
| 22501 | |||
| 22502 |
1/2✓ Branch 0 taken 4974034 times.
✗ Branch 1 not taken.
|
4973998 | innobase_srv_conc_force_exit_innodb(trx); |
| 22503 | |||
| 22504 |
1/2✓ Branch 0 taken 4974027 times.
✗ Branch 1 not taken.
|
4974034 | TrxInInnoDB trx_in_innodb(trx); |
| 22505 | |||
| 22506 |
5/6✓ Branch 0 taken 4974041 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4973906 times.
✓ Branch 3 taken 135 times.
✓ Branch 4 taken 121 times.
✓ Branch 5 taken 4973928 times.
|
9947941 | if (trx_in_innodb.is_aborted() || |
| 22507 |
2/4✓ Branch 0 taken 4973914 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4973917 times.
|
4973906 | DBUG_EVALUATE_IF("simulate_xa_failure_prepare_in_engine", 1, 0)) { |
| 22508 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | innobase_rollback(hton, thd, prepare_trx); |
| 22509 | |||
| 22510 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd)); |
| 22511 | } | ||
| 22512 | |||
| 22513 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 4973855 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4973855 times.
|
4973928 | if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) { |
| 22514 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE); | |
| 22515 | } | ||
| 22516 | |||
| 22517 |
4/4✓ Branch 0 taken 4437125 times.
✓ Branch 1 taken 536724 times.
✓ Branch 2 taken 2045361 times.
✓ Branch 3 taken 2928542 times.
|
9411028 | if (prepare_trx || |
| 22518 |
3/4✓ Branch 0 taken 4437179 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1508634 times.
✓ Branch 3 taken 2928545 times.
|
4437125 | (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { |
| 22519 | /* We were instructed to prepare the whole transaction, or | ||
| 22520 | this is an SQL statement end and autocommit is on */ | ||
| 22521 | |||
| 22522 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2045354 times.
|
2045361 | ut_ad(trx_is_registered_for_2pc(trx)); |
| 22523 | |||
| 22524 |
1/2✓ Branch 0 taken 2045370 times.
✗ Branch 1 not taken.
|
2045354 | dberr_t err = trx_prepare_for_mysql(trx); |
| 22525 | |||
| 22526 |
5/6✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2045369 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2045370 times.
|
2045370 | ut_ad(err == DB_SUCCESS || err == DB_FORCED_ABORT); |
| 22527 | |||
| 22528 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2045369 times.
|
2045370 | if (err == DB_FORCED_ABORT) { |
| 22529 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | innobase_rollback(hton, thd, prepare_trx); |
| 22530 | |||
| 22531 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd)); |
| 22532 | } | ||
| 22533 | |||
| 22534 |
4/6✓ Branch 0 taken 2045370 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2045367 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
2045369 | DBUG_EXECUTE_IF("crash_innodb_after_prepare", DBUG_SUICIDE();); |
| 22535 | |||
| 22536 | } else { | ||
| 22537 | /* We just mark the SQL statement ended and do not do a | ||
| 22538 | transaction prepare */ | ||
| 22539 | |||
| 22540 | /* If we had reserved the auto-inc lock for some | ||
| 22541 | table in this SQL statement we release it now */ | ||
| 22542 | |||
| 22543 |
1/2✓ Branch 0 taken 2928557 times.
✗ Branch 1 not taken.
|
2928542 | lock_unlock_table_autoinc(trx); |
| 22544 | |||
| 22545 | /* Store the current undo_no of the transaction so that we | ||
| 22546 | know where to roll back if we have to roll back the next | ||
| 22547 | SQL statement */ | ||
| 22548 | |||
| 22549 |
1/2✓ Branch 0 taken 2928549 times.
✗ Branch 1 not taken.
|
2928557 | trx_mark_sql_stat_end(trx); |
| 22550 | } | ||
| 22551 | |||
| 22552 |
5/6✓ Branch 0 taken 4973922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4973296 times.
✓ Branch 3 taken 626 times.
✓ Branch 4 taken 4437204 times.
✓ Branch 5 taken 536092 times.
|
9411119 | if (thd_sql_command(thd) != SQLCOM_XA_PREPARE && |
| 22553 | 4437203 | (prepare_trx || | |
| 22554 |
3/4✓ Branch 0 taken 4437203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1508647 times.
✓ Branch 3 taken 2928556 times.
|
4437204 | !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { |
| 22555 | /* For mysqlbackup to work the order of transactions in binlog | ||
| 22556 | and InnoDB must be the same. Consider the situation | ||
| 22557 | |||
| 22558 | thread1> prepare; write to binlog; ... | ||
| 22559 | <context switch> | ||
| 22560 | thread2> prepare; write to binlog; commit | ||
| 22561 | thread1> ... commit | ||
| 22562 | |||
| 22563 | The server guarantees that writes to the binary log | ||
| 22564 | and commits are in the same order, so we do not have | ||
| 22565 | to handle this case. */ | ||
| 22566 | } | ||
| 22567 | |||
| 22568 | 4973921 | return (0); | |
| 22569 | 4974043 | } | |
| 22570 | |||
| 22571 | /** This function is used to recover X/Open XA distributed transactions. | ||
| 22572 | @return number of prepared transactions stored in xid_list */ | ||
| 22573 | 9543 | static int innobase_xa_recover( | |
| 22574 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 22575 | XA_recover_txn *txn_list, /*!< in/out: prepared transactions */ | ||
| 22576 | uint len, /*!< in: number of slots in xid_list */ | ||
| 22577 | MEM_ROOT *mem_root) /*!< in: memory for table names */ | ||
| 22578 | { | ||
| 22579 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9543 times.
|
9543 | assert(hton == innodb_hton_ptr); |
| 22580 | |||
| 22581 |
2/4✓ Branch 0 taken 9543 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9543 times.
|
9543 | if (len == 0 || txn_list == nullptr) { |
| 22582 | ✗ | return (0); | |
| 22583 | } | ||
| 22584 | |||
| 22585 | 9543 | return (trx_recover_for_mysql(txn_list, len, mem_root)); | |
| 22586 | } | ||
| 22587 | |||
| 22588 | 9543 | static int innobase_xa_recover_prepared_in_tc(handlerton *hton, | |
| 22589 | Xa_state_list &xa_list) { | ||
| 22590 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9543 times.
|
9543 | assert(hton == innodb_hton_ptr); |
| 22591 | |||
| 22592 | 9543 | return (trx_recover_tc_for_mysql(xa_list)); | |
| 22593 | } | ||
| 22594 | |||
| 22595 | /** This function is used to commit one X/Open XA distributed transaction | ||
| 22596 | which is in the prepared state | ||
| 22597 | @return 0 or error number */ | ||
| 22598 | 608 | static xa_status_code innobase_commit_by_xid( | |
| 22599 | handlerton *hton, XID *xid) /*!< in: X/Open XA transaction identification */ | ||
| 22600 | { | ||
| 22601 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
|
608 | assert(hton == innodb_hton_ptr); |
| 22602 | |||
| 22603 | 608 | trx_t *trx = trx_get_trx_by_xid(xid); | |
| 22604 | |||
| 22605 |
2/2✓ Branch 0 taken 592 times.
✓ Branch 1 taken 16 times.
|
608 | if (trx != nullptr) { |
| 22606 |
1/2✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
|
592 | TrxInInnoDB trx_in_innodb(trx); |
| 22607 | #ifdef WITH_WSREP | ||
| 22608 | 592 | trx->wsrep_recover_xid = xid; | |
| 22609 | #endif /* WITH_WSREP */ | ||
| 22610 | |||
| 22611 |
1/2✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
|
592 | innobase_commit_low(trx); |
| 22612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 592 times.
|
592 | ut_ad(trx->mysql_thd == nullptr); |
| 22613 | /* use cases are: disconnected xa, slave xa, recovery */ | ||
| 22614 | 592 | trx_deregister_from_2pc(trx); | |
| 22615 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 592 times.
|
592 | ut_ad(!trx->will_lock); /* trx cache requirement */ |
| 22616 | |||
| 22617 | #ifdef WITH_WSREP | ||
| 22618 | 592 | trx->wsrep_recover_xid = NULL; | |
| 22619 | #endif /* WITH_WSREP */ | ||
| 22620 | |||
| 22621 |
1/2✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
|
592 | trx_free_for_background(trx); |
| 22622 | |||
| 22623 | 592 | return (XA_OK); | |
| 22624 | 592 | } else { | |
| 22625 | 16 | return (XAER_NOTA); | |
| 22626 | } | ||
| 22627 | } | ||
| 22628 | |||
| 22629 | /** This function is used to rollback one X/Open XA distributed transaction | ||
| 22630 | which is in the prepared state | ||
| 22631 | @return 0 or error number */ | ||
| 22632 | 324 | static xa_status_code innobase_rollback_by_xid( | |
| 22633 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 22634 | XID *xid) /*!< in: X/Open XA transaction | ||
| 22635 | identification */ | ||
| 22636 | { | ||
| 22637 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
|
324 | assert(hton == innodb_hton_ptr); |
| 22638 | |||
| 22639 | 324 | trx_t *trx = trx_get_trx_by_xid(xid); | |
| 22640 | |||
| 22641 |
2/2✓ Branch 0 taken 309 times.
✓ Branch 1 taken 15 times.
|
324 | if (trx != nullptr) { |
| 22642 |
1/2✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
|
309 | TrxInInnoDB trx_in_innodb(trx); |
| 22643 | |||
| 22644 |
1/2✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
|
309 | int ret = innobase_rollback_trx(trx); |
| 22645 | |||
| 22646 | 309 | trx_deregister_from_2pc(trx); | |
| 22647 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
|
309 | ut_ad(!trx->will_lock); |
| 22648 |
1/2✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
|
309 | trx_free_for_background(trx); |
| 22649 | |||
| 22650 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
|
309 | return (ret != 0 ? XAER_RMERR : XA_OK); |
| 22651 | 309 | } else { | |
| 22652 | 15 | return (XAER_NOTA); | |
| 22653 | } | ||
| 22654 | } | ||
| 22655 | |||
| 22656 | 590 | static int innobase_set_prepared_in_tc(handlerton *hton, THD *thd) { | |
| 22657 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
|
590 | assert(hton == innodb_hton_ptr); |
| 22658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
|
590 | assert(thd != nullptr); |
| 22659 | |||
| 22660 | 590 | trx_t *trx = check_trx_exists(thd); | |
| 22661 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
|
590 | assert(trx != nullptr); |
| 22662 | |||
| 22663 | 590 | thd_get_xid(thd, (MYSQL_XID *)trx->xid); | |
| 22664 | |||
| 22665 | 590 | innobase_srv_conc_force_exit_innodb(trx); | |
| 22666 | |||
| 22667 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 590 times.
|
590 | ut_ad(trx_is_registered_for_2pc(trx) || thd == nullptr); |
| 22668 | |||
| 22669 | 590 | dberr_t err = trx_set_prepared_in_tc_for_mysql(trx); | |
| 22670 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 590 times.
|
590 | ut_ad(err != DB_FORCED_ABORT); |
| 22671 | |||
| 22672 | 590 | return convert_error_code_to_mysql(err, 0, thd); | |
| 22673 | } | ||
| 22674 | |||
| 22675 | 62 | static xa_status_code innobase_set_prepared_in_tc_by_xid(handlerton *hton, | |
| 22676 | XID *xid) { | ||
| 22677 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | assert(hton == innodb_hton_ptr); |
| 22678 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | assert(xid != nullptr); |
| 22679 | |||
| 22680 | 62 | trx_t *trx = trx_get_trx_by_xid(xid); | |
| 22681 | |||
| 22682 |
1/2✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
|
62 | if (trx != nullptr) { |
| 22683 | /* Side effect of retrieving the transaction is XID being set to null */ | ||
| 22684 | 62 | *trx->xid = *xid; | |
| 22685 | |||
| 22686 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 6 times.
|
62 | if (trx_is_prepared_in_tc(trx)) { |
| 22687 | 56 | return XA_OK; | |
| 22688 | } | ||
| 22689 | |||
| 22690 | 6 | innobase_srv_conc_force_exit_innodb(trx); | |
| 22691 | |||
| 22692 | 6 | dberr_t err = trx_set_prepared_in_tc_for_mysql(trx); | |
| 22693 | |||
| 22694 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | ut_ad(err != DB_FORCED_ABORT); |
| 22695 | |||
| 22696 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | return (err != DB_SUCCESS ? XAER_RMERR : XA_OK); |
| 22697 | } else { | ||
| 22698 | ✗ | return (XAER_NOTA); | |
| 22699 | } | ||
| 22700 | } | ||
| 22701 | |||
| 22702 | /** */ | ||
| 22703 | |||
| 22704 | 260 | bool ha_innobase::check_if_incompatible_data(HA_CREATE_INFO *info, | |
| 22705 | uint table_changes) { | ||
| 22706 | 260 | innobase_copy_frm_flags_from_create_info(m_prebuilt->table, info); | |
| 22707 | |||
| 22708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
|
260 | if (table_changes != IS_EQUAL_YES) { |
| 22709 | ✗ | return (COMPATIBLE_DATA_NO); | |
| 22710 | } | ||
| 22711 | |||
| 22712 | /* Check that auto_increment value was not changed */ | ||
| 22713 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
|
260 | if ((info->used_fields & HA_CREATE_USED_AUTO) && |
| 22714 | ✗ | info->auto_increment_value != 0) { | |
| 22715 | ✗ | return (COMPATIBLE_DATA_NO); | |
| 22716 | } | ||
| 22717 | |||
| 22718 | /* Check that row format didn't change */ | ||
| 22719 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
|
260 | if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) && |
| 22720 | ✗ | info->row_type != table->s->real_row_type) { | |
| 22721 | ✗ | return (COMPATIBLE_DATA_NO); | |
| 22722 | } | ||
| 22723 | |||
| 22724 | /* Specifying KEY_BLOCK_SIZE requests a rebuild of the table. */ | ||
| 22725 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
|
260 | if (info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) { |
| 22726 | ✗ | return (COMPATIBLE_DATA_NO); | |
| 22727 | } | ||
| 22728 | |||
| 22729 | 260 | return (COMPATIBLE_DATA_YES); | |
| 22730 | } | ||
| 22731 | |||
| 22732 | /** This function reads zip dict-related info from SYS_ZIP_DICT | ||
| 22733 | and SYS_ZIP_DICT_COLS for all columns marked with | ||
| 22734 | COLUMN_FORMAT_TYPE_COMPRESSED flag and updates | ||
| 22735 | zip_dict_name / zip_dict_data for those which have associated | ||
| 22736 | compression dictionaries. | ||
| 22737 | |||
| 22738 | @param thd Thread handle, used to determine whether it is | ||
| 22739 | necessary to lock dict_sys mutex | ||
| 22740 | @param part_name Full table name (including partition part). | ||
| 22741 | Must be non-NULL only if called from | ||
| 22742 | ha_partition. | ||
| 22743 | */ | ||
| 22744 | 22 | void ha_innobase::upgrade_update_field_with_zip_dict_info( | |
| 22745 | THD *thd, const char *part_name) { | ||
| 22746 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | DBUG_ENTER("upgrade_update_field_with_zip_dict_info"); |
| 22747 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | ut_ad(srv_is_upgrade_mode); |
| 22748 | |||
| 22749 | char norm_name[FN_REFLEN]; | ||
| 22750 |
3/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
|
34 | normalize_table_name( |
| 22751 | 12 | norm_name, part_name ? part_name : table_share->normalized_path.str); | |
| 22752 | |||
| 22753 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | const innodb_session_t *const innodb_session = thd_to_innodb_session(thd); |
| 22754 | 22 | bool dict_locked = innodb_session->is_dict_mutex_locked(); | |
| 22755 | |||
| 22756 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | dict_table_t *const ib_table = dict_table_open_on_name( |
| 22757 | norm_name, dict_locked, false, DICT_ERR_IGNORE_NONE); | ||
| 22758 | |||
| 22759 | /* if dict_table_open_on_name() returns NULL, then it means that | ||
| 22760 | TABLE_SHARE is populated for a table being created and we can | ||
| 22761 | skip filling zip dict info here */ | ||
| 22762 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
22 | if (ib_table == nullptr) DBUG_VOID_RETURN; |
| 22763 | |||
| 22764 | 22 | const table_id_t ib_table_id = ib_table->id - DICT_MAX_DD_TABLES; | |
| 22765 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | dict_table_close(ib_table, dict_locked, false); |
| 22766 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 22 times.
|
68 | for (uint i = 0; i < table_share->fields; ++i) { |
| 22767 | 46 | Field *const field = table_share->field[i]; | |
| 22768 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 20 times.
|
46 | if (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED) { |
| 22769 | 26 | bool reference_found = false; | |
| 22770 | 26 | ulint dict_id = 0; | |
| 22771 |
3/5✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
26 | switch (dict_get_dictionary_id_by_key(ib_table_id, i, &dict_id)) { |
| 22772 | 16 | case DB_SUCCESS: | |
| 22773 | 16 | reference_found = true; | |
| 22774 | 16 | break; | |
| 22775 | 10 | case DB_RECORD_NOT_FOUND: | |
| 22776 | 10 | reference_found = false; | |
| 22777 | 10 | break; | |
| 22778 | ✗ | default: | |
| 22779 | ✗ | ut_error; | |
| 22780 | } | ||
| 22781 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 10 times.
|
26 | if (reference_found) { |
| 22782 | 16 | char *local_name = nullptr; | |
| 22783 | 16 | ulint local_name_len = 0; | |
| 22784 | 16 | char *local_data = nullptr; | |
| 22785 | 16 | ulint local_data_len = 0; | |
| 22786 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (dict_get_dictionary_info_by_id(dict_id, &local_name, |
| 22787 | &local_name_len, &local_data, | ||
| 22788 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | &local_data_len) != DB_SUCCESS) |
| 22789 | ✗ | ut_error; | |
| 22790 | else { | ||
| 22791 | 16 | field->zip_dict_name.str = local_name; | |
| 22792 | 16 | field->zip_dict_name.length = local_name_len; | |
| 22793 | 16 | field->zip_dict_data.str = local_data; | |
| 22794 | 16 | field->zip_dict_data.length = local_data_len; | |
| 22795 | } | ||
| 22796 | } else { | ||
| 22797 | 10 | field->zip_dict_name.str = nullptr; | |
| 22798 | 10 | field->zip_dict_name.length = 0; | |
| 22799 | 10 | field->zip_dict_data.str = nullptr; | |
| 22800 | 10 | field->zip_dict_data.length = 0; | |
| 22801 | } | ||
| 22802 | } | ||
| 22803 | } | ||
| 22804 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | DBUG_VOID_RETURN; |
| 22805 | } | ||
| 22806 | |||
| 22807 | /** Update the system variable innodb_io_capacity_max using the "saved" | ||
| 22808 | value. This function is registered as a callback with MySQL. */ | ||
| 22809 | 10 | static void innodb_io_capacity_max_update( | |
| 22810 | THD *thd, /*!< in: thread handle */ | ||
| 22811 | SYS_VAR *, /*!< in: pointer to | ||
| 22812 | system variable */ | ||
| 22813 | void *, /*!< out: where the | ||
| 22814 | formal string goes */ | ||
| 22815 | const void *save) /*!< in: immediate result | ||
| 22816 | from check function */ | ||
| 22817 | { | ||
| 22818 | 10 | ulong in_val = *static_cast<const ulong *>(save); | |
| 22819 | |||
| 22820 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
|
10 | if (in_val < srv_io_capacity) { |
| 22821 | 2 | in_val = srv_io_capacity; | |
| 22822 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22823 | "innodb_io_capacity_max cannot be" | ||
| 22824 | " set lower than innodb_io_capacity."); | ||
| 22825 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22826 | "Setting innodb_io_capacity_max to %lu", | ||
| 22827 | srv_io_capacity); | ||
| 22828 | } | ||
| 22829 | |||
| 22830 | 10 | srv_max_io_capacity = in_val; | |
| 22831 | 10 | } | |
| 22832 | |||
| 22833 | /** Update the system variable innodb_io_capacity using the "saved" | ||
| 22834 | value. This function is registered as a callback with MySQL. */ | ||
| 22835 | 18 | static void innodb_io_capacity_update( | |
| 22836 | THD *thd, /*!< in: thread handle */ | ||
| 22837 | SYS_VAR *, /*!< in: pointer to system variable */ | ||
| 22838 | void *, /*!< out: where the formal string goes */ | ||
| 22839 | const void *save) /*!< in: immediate result from check function */ | ||
| 22840 | { | ||
| 22841 | 18 | ulong in_val = *static_cast<const ulong *>(save); | |
| 22842 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 17 times.
|
18 | if (in_val > srv_max_io_capacity) { |
| 22843 | 1 | in_val = srv_max_io_capacity; | |
| 22844 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22845 | "innodb_io_capacity cannot be set" | ||
| 22846 | " higher than innodb_io_capacity_max."); | ||
| 22847 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22848 | "Setting innodb_io_capacity to %lu", | ||
| 22849 | srv_max_io_capacity); | ||
| 22850 | } | ||
| 22851 | |||
| 22852 | 18 | srv_io_capacity = in_val; | |
| 22853 | 18 | } | |
| 22854 | |||
| 22855 | /** Update the system variable innodb_max_dirty_pages_pct using the "saved" | ||
| 22856 | value. This function is registered as a callback with MySQL. */ | ||
| 22857 | 36 | static void innodb_max_dirty_pages_pct_update( | |
| 22858 | THD *thd, /*!< in: thread handle */ | ||
| 22859 | SYS_VAR *, /*!< in: pointer to | ||
| 22860 | system variable */ | ||
| 22861 | void *, /*!< out: where the | ||
| 22862 | formal string goes */ | ||
| 22863 | const void *save) /*!< in: immediate result | ||
| 22864 | from check function */ | ||
| 22865 | { | ||
| 22866 | 36 | double in_val = *static_cast<const double *>(save); | |
| 22867 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
|
36 | if (in_val < srv_max_dirty_pages_pct_lwm) { |
| 22868 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22869 | "innodb_max_dirty_pages_pct cannot be" | ||
| 22870 | " set lower than" | ||
| 22871 | " innodb_max_dirty_pages_pct_lwm."); | ||
| 22872 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22873 | "Lowering" | ||
| 22874 | " innodb_max_dirty_page_pct_lwm to %lf", | ||
| 22875 | in_val); | ||
| 22876 | |||
| 22877 | 2 | srv_max_dirty_pages_pct_lwm = in_val; | |
| 22878 | } | ||
| 22879 | |||
| 22880 | 36 | srv_max_buf_pool_modified_pct = in_val; | |
| 22881 | 36 | } | |
| 22882 | |||
| 22883 | /** Update the system variable innodb_max_dirty_pages_pct_lwm using the | ||
| 22884 | "saved" value. This function is registered as a callback with MySQL. */ | ||
| 22885 | 20 | static void innodb_max_dirty_pages_pct_lwm_update( | |
| 22886 | THD *thd, /*!< in: thread handle */ | ||
| 22887 | SYS_VAR *, /*!< in: pointer to | ||
| 22888 | system variable */ | ||
| 22889 | void *, /*!< out: where the | ||
| 22890 | formal string goes */ | ||
| 22891 | const void *save) /*!< in: immediate result | ||
| 22892 | from check function */ | ||
| 22893 | { | ||
| 22894 | 20 | double in_val = *static_cast<const double *>(save); | |
| 22895 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
|
20 | if (in_val > srv_max_buf_pool_modified_pct) { |
| 22896 | 2 | in_val = srv_max_buf_pool_modified_pct; | |
| 22897 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22898 | "innodb_max_dirty_pages_pct_lwm" | ||
| 22899 | " cannot be set higher than" | ||
| 22900 | " innodb_max_dirty_pages_pct."); | ||
| 22901 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22902 | "Setting innodb_max_dirty_page_pct_lwm" | ||
| 22903 | " to %lf", | ||
| 22904 | in_val); | ||
| 22905 | } | ||
| 22906 | |||
| 22907 | 20 | srv_max_dirty_pages_pct_lwm = in_val; | |
| 22908 | 20 | } | |
| 22909 | |||
| 22910 | 39 | static int innodb_stopword_table_validate(THD *thd, SYS_VAR *, void *save, | |
| 22911 | struct st_mysql_value *value) { | ||
| 22912 | const char *stopword_table_name; | ||
| 22913 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 22914 | 39 | int len = sizeof(buff); | |
| 22915 | 39 | int ret = 1; | |
| 22916 | |||
| 22917 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | ut_a(save != nullptr); |
| 22918 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | ut_a(value != nullptr); |
| 22919 | |||
| 22920 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | stopword_table_name = value->val_str(value, buff, &len); |
| 22921 | |||
| 22922 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 14 times.
|
39 | if (stopword_table_name != nullptr) { |
| 22923 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
|
25 | if (stopword_table_name == buff) { |
| 22924 | /* Allocate from thd's memroot */ | ||
| 22925 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | stopword_table_name = thd_strmake(thd, stopword_table_name, len); |
| 22926 | } | ||
| 22927 | } | ||
| 22928 | |||
| 22929 | /* Validate the stopword table's (if supplied) existence and | ||
| 22930 | of the right format */ | ||
| 22931 |
7/8✓ Branch 0 taken 25 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 34 times.
✓ Branch 7 taken 5 times.
|
39 | if (!stopword_table_name || fts_valid_stopword_table(stopword_table_name)) { |
| 22932 | 34 | *static_cast<const char **>(save) = stopword_table_name; | |
| 22933 | 34 | ret = 0; | |
| 22934 | } | ||
| 22935 | |||
| 22936 | 39 | return (ret); | |
| 22937 | } | ||
| 22938 | |||
| 22939 | /** | ||
| 22940 | Utility method that checks if user provided valid value. | ||
| 22941 | If yes, then store that in the save variable. | ||
| 22942 | @return 0 on success, 1 on failure. | ||
| 22943 | */ | ||
| 22944 | 1100 | static int check_func_bool(THD *, SYS_VAR *, void *save, | |
| 22945 | st_mysql_value *value) { | ||
| 22946 | int result; | ||
| 22947 |
2/2✓ Branch 0 taken 993 times.
✓ Branch 1 taken 107 times.
|
1100 | if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING) { |
| 22948 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 22949 | 993 | int length = sizeof(buff); | |
| 22950 | |||
| 22951 |
1/2✓ Branch 0 taken 993 times.
✗ Branch 1 not taken.
|
993 | const char *str = value->val_str(value, buff, &length); |
| 22952 | |||
| 22953 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 993 times.
|
997 | if (str == nullptr) return 1; |
| 22954 | |||
| 22955 |
1/2✓ Branch 0 taken 993 times.
✗ Branch 1 not taken.
|
993 | result = find_type(&bool_typelib, str, length, true) - 1; |
| 22956 | |||
| 22957 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 989 times.
|
993 | if (result < 0) return 1; |
| 22958 | } else { | ||
| 22959 | long long tmp; | ||
| 22960 |
2/4✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 107 times.
|
115 | if (value->val_int(value, &tmp) < 0) return 1; |
| 22961 |
4/4✓ Branch 0 taken 103 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 99 times.
|
107 | if (tmp > 1 || tmp < 0) return 1; |
| 22962 | 99 | result = static_cast<int>(tmp); | |
| 22963 | } | ||
| 22964 | 1088 | *(bool *)save = result ? true : false; | |
| 22965 | 1088 | return 0; | |
| 22966 | } | ||
| 22967 | |||
| 22968 | /** | ||
| 22969 | Utility method that checks if user has correct session administrative | ||
| 22970 | dynamic privileges. | ||
| 22971 | @return 0 on success, 1 on failure. | ||
| 22972 | */ | ||
| 22973 | 886 | static int check_session_admin(THD *thd) { | |
| 22974 | 886 | Security_context *sctx = thd->security_context(); | |
| 22975 | 886 | if (!sctx->has_global_grant(STRING_WITH_LEN("SESSION_VARIABLES_ADMIN")) | |
| 22976 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 883 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 885 times.
|
889 | .first && |
| 22977 | 3 | !sctx->has_global_grant(STRING_WITH_LEN("SYSTEM_VARIABLES_ADMIN")) | |
| 22978 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | .first) { |
| 22979 | 1 | return 1; | |
| 22980 | } | ||
| 22981 | 885 | return 0; | |
| 22982 | } | ||
| 22983 | |||
| 22984 | /** | ||
| 22985 | Check if SESSION_VARIABLES_ADMIN granted. Throw SQL error if not. | ||
| 22986 | We also accept SYSTEM_VARIABLES_ADMIN since it doesn't make a lot of | ||
| 22987 | sense to be allowed to set the global variable and not the session ones. | ||
| 22988 | |||
| 22989 | @param thd the session context | ||
| 22990 | @param var the system variable to set value for | ||
| 22991 | @param save set the updated value | ||
| 22992 | @param value A struct that reads us the values from mysqld | ||
| 22993 | |||
| 22994 | @retval 1 failure | ||
| 22995 | @retval 0 success | ||
| 22996 | */ | ||
| 22997 | 886 | static int innodb_check_session_admin(THD *thd, SYS_VAR *var, void *save, | |
| 22998 | struct st_mysql_value *value) { | ||
| 22999 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 885 times.
|
886 | if (check_session_admin(thd)) { |
| 23000 | 1 | my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), | |
| 23001 | "SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN"); | ||
| 23002 | 1 | return 1; | |
| 23003 | } | ||
| 23004 | 885 | return check_func_bool(thd, var, save, value); | |
| 23005 | } | ||
| 23006 | |||
| 23007 | 5 | static void innodb_srv_buffer_pool_in_core_file_update(THD *, SYS_VAR *, void *, | |
| 23008 | const void *save) { | ||
| 23009 | 5 | srv_buffer_pool_in_core_file = *(bool *)save; | |
| 23010 | 5 | buf_pool_update_madvise(); | |
| 23011 | 5 | } | |
| 23012 | |||
| 23013 | /** Validate the requested buffer pool size. Also, reserve the necessary | ||
| 23014 | memory needed for buffer pool resize. | ||
| 23015 | @param[in] thd thread handle | ||
| 23016 | @param[in] buffer_pool_size buffer pool size value to be validated | ||
| 23017 | @param[out] aligned_buffer_pool_size aligned version of buffer_pool_size | ||
| 23018 | if validation succeeds, else original value passed in | ||
| 23019 | @return true on success, false on failure. | ||
| 23020 | */ | ||
| 23021 | 30 | static bool innodb_buffer_pool_size_validate(THD *thd, | |
| 23022 | longlong buffer_pool_size, | ||
| 23023 | ulint &aligned_buffer_pool_size) { | ||
| 23024 | 30 | os_rmb; | |
| 23025 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 29 times.
|
30 | if (srv_buf_pool_old_size != srv_buf_pool_size) { |
| 23026 | 1 | push_warning(thd, ER_BUFPOOL_RESIZE_INPROGRESS); | |
| 23027 | 1 | return false; | |
| 23028 | } | ||
| 23029 | |||
| 23030 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
29 | if (srv_buf_pool_instances > 1 && |
| 23031 | buffer_pool_size < BUF_POOL_SIZE_THRESHOLD) { | ||
| 23032 | #ifdef UNIV_DEBUG | ||
| 23033 | /* Ignore 1G constraint to enable mulitple instances | ||
| 23034 | for debug and test. */ | ||
| 23035 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (srv_buf_pool_debug) { |
| 23036 | 2 | goto debug_set; | |
| 23037 | } | ||
| 23038 | #endif /* UNIV_DEBUG */ | ||
| 23039 | |||
| 23040 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23041 | "Cannot update innodb_buffer_pool_size" | ||
| 23042 | " to less than 1GB if" | ||
| 23043 | " innodb_buffer_pool_instances > 1."); | ||
| 23044 | ✗ | return false; | |
| 23045 | } | ||
| 23046 | |||
| 23047 | #ifdef UNIV_DEBUG | ||
| 23048 | 27 | debug_set: | |
| 23049 | #endif /* UNIV_DEBUG */ | ||
| 23050 | |||
| 23051 | if constexpr (sizeof(ulint) == 4) { | ||
| 23052 | if (buffer_pool_size > UINT_MAX32) { | ||
| 23053 | push_warning_printf( | ||
| 23054 | thd, Sql_condition::SL_WARNING, ER_WRONG_VALUE_FOR_VAR, | ||
| 23055 | ER_THD(thd, ER_WRONG_VALUE_FOR_VAR), "innodb_buffer_pool_size", | ||
| 23056 | std::to_string(buffer_pool_size).c_str()); | ||
| 23057 | return false; | ||
| 23058 | } | ||
| 23059 | } | ||
| 23060 | |||
| 23061 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
|
29 | if (!innodb_empty_free_list_algorithm_allowed( |
| 23062 | static_cast<srv_empty_free_list_t>(srv_empty_free_list_algorithm), | ||
| 23063 | buffer_pool_size)) { | ||
| 23064 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23065 | "Cannot update innodb_buffer_pool_size to less than " | ||
| 23066 | "20MB per instance with " | ||
| 23067 | "innodb_empty_free_list_algorithm = backoff."); | ||
| 23068 | 1 | return false; | |
| 23069 | } | ||
| 23070 | |||
| 23071 | 28 | aligned_buffer_pool_size = | |
| 23072 | 28 | buf_pool_size_align(static_cast<ulint>(buffer_pool_size)); | |
| 23073 | |||
| 23074 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3 times.
|
28 | if (srv_buf_pool_size == static_cast<ulint>(buffer_pool_size)) { |
| 23075 | /* nothing to do */ | ||
| 23076 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
|
25 | } else if (srv_buf_pool_size == aligned_buffer_pool_size) { |
| 23077 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23078 | "InnoDB: Cannot resize buffer pool to lesser than" | ||
| 23079 | " chunk size of %llu bytes.", | ||
| 23080 | srv_buf_pool_chunk_unit); | ||
| 23081 | } else { | ||
| 23082 | 23 | srv_buf_pool_size = aligned_buffer_pool_size; | |
| 23083 | 23 | os_wmb; | |
| 23084 | |||
| 23085 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
|
23 | if (buffer_pool_size != static_cast<longlong>(aligned_buffer_pool_size)) { |
| 23086 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | push_warning_printf( |
| 23087 | thd, Sql_condition::SL_WARNING, ER_TRUNCATED_WRONG_VALUE, | ||
| 23088 | ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "innodb_buffer_pool_size", | ||
| 23089 | 14 | std::to_string(buffer_pool_size).c_str()); | |
| 23090 | } | ||
| 23091 | } | ||
| 23092 | |||
| 23093 | 28 | return true; | |
| 23094 | } | ||
| 23095 | |||
| 23096 | /** Set the variable tbsp_extend_and_initialize. This function is registered | ||
| 23097 | as a callback to MySQL. | ||
| 23098 | On Linux, the variable tbsp_extend_and_initialize will be set to the value | ||
| 23099 | passed by the user. A warning will be printed that the user is not | ||
| 23100 | allowed to change the value if the server is running on Windows | ||
| 23101 | or other posix implementations. | ||
| 23102 | @param[in] thd thread handle | ||
| 23103 | @param[out] var_ptr value to be set after the validation | ||
| 23104 | @param[in] save value set by the user */ | ||
| 23105 | 19 | static void innodb_extend_and_initialize_update(THD *thd, SYS_VAR *, | |
| 23106 | void *var_ptr, | ||
| 23107 | const void *save) { | ||
| 23108 | 19 | bool extend_and_initialize [[maybe_unused]] = | |
| 23109 | *static_cast<const bool *>(save); | ||
| 23110 | #if !defined(NO_FALLOCATE) && defined(UNIV_LINUX) | ||
| 23111 | 19 | *static_cast<bool *>(var_ptr) = extend_and_initialize; | |
| 23112 | #else /* !NO_FALLOCATE && UNIV_LINUX */ | ||
| 23113 | push_warning_printf(thd, Sql_condition::SL_WARNING, | ||
| 23114 | ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED, | ||
| 23115 | ER_THD(thd, ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED), | ||
| 23116 | "innodb_extend_and_initialize"); | ||
| 23117 | *static_cast<bool *>(var_ptr) = true; | ||
| 23118 | #endif /* !NO_FALLOCATE && UNIV_LINUX */ | ||
| 23119 | 19 | } | |
| 23120 | |||
| 23121 | /** Update the system variable innodb_buffer_pool_size using the "saved" | ||
| 23122 | value. This function is registered as a callback with MySQL. | ||
| 23123 | @param[in] thd thread handle | ||
| 23124 | @param[out] var_ptr where the formal string goes | ||
| 23125 | @param[in] save immediate result from check function */ | ||
| 23126 | 30 | static void innodb_buffer_pool_size_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 23127 | const void *save) { | ||
| 23128 | 30 | longlong requested_buffer_pool_size = *static_cast<const longlong *>(save); | |
| 23129 | 30 | ulint aligned_buffer_pool_size = 0u; | |
| 23130 |
3/4✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 2 times.
|
30 | if (innodb_buffer_pool_size_validate(thd, requested_buffer_pool_size, |
| 23131 | aligned_buffer_pool_size)) { | ||
| 23132 | 28 | snprintf(export_vars.innodb_buffer_pool_resize_status, | |
| 23133 | sizeof(export_vars.innodb_buffer_pool_resize_status), | ||
| 23134 | "Requested to resize buffer pool."); | ||
| 23135 | |||
| 23136 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | os_event_set(srv_buf_resize_event); |
| 23137 | |||
| 23138 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
56 | ib::info(ER_IB_MSG_573) |
| 23139 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | << export_vars.innodb_buffer_pool_resize_status |
| 23140 |
3/6✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
|
28 | << " (new size: " << aligned_buffer_pool_size << " bytes)"; |
| 23141 | |||
| 23142 | 28 | *static_cast<longlong *>(var_ptr) = aligned_buffer_pool_size; | |
| 23143 | } | ||
| 23144 | 30 | } | |
| 23145 | |||
| 23146 | /** Update the system variable innobase_deadlock_detect using the "saved" value. | ||
| 23147 | Makes sure to "wake up" the dedicated deadlock detector thread if needed. | ||
| 23148 | This function is registered as a callback with MySQL. | ||
| 23149 | @param[in] save immediate result from check function */ | ||
| 23150 | 14 | static void innobase_deadlock_detect_update(THD *, SYS_VAR *, void *, | |
| 23151 | const void *save) { | ||
| 23152 | 14 | innobase_deadlock_detect = *(bool *)save; | |
| 23153 | /* In case deadlock detection was disabled for a long time it could happen | ||
| 23154 | that all clients have deadlocked with each other and thus they stopped | ||
| 23155 | changing the wait-for graph, which in turn causes deadlock detection to not | ||
| 23156 | observe any action and thus it will not search for deadlocks. So if we now | ||
| 23157 | change from OFF to ON we need to "kick-start" the process. It never hurts to | ||
| 23158 | do so, so we do it even if we check from ON to OFF */ | ||
| 23159 | 14 | lock_wait_request_check_for_cycles(); | |
| 23160 | 14 | } | |
| 23161 | |||
| 23162 | /** Check whether valid argument given to "innodb_fts_internal_tbl_name" | ||
| 23163 | This function is registered as a callback with MySQL. | ||
| 23164 | @param[in] thd thread handle | ||
| 23165 | @param[out] save immediate result for update function | ||
| 23166 | @param[in] value incoming string | ||
| 23167 | @return 0 for valid stopword table */ | ||
| 23168 | 32 | static int innodb_internal_table_validate(THD *thd, SYS_VAR *, void *save, | |
| 23169 | struct st_mysql_value *value) { | ||
| 23170 | const char *table_name; | ||
| 23171 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 23172 | 32 | int len = sizeof(buff); | |
| 23173 | 32 | int ret = 1; | |
| 23174 | dict_table_t *user_table; | ||
| 23175 | 32 | MDL_ticket *mdl = nullptr; | |
| 23176 | |||
| 23177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | ut_a(save != nullptr); |
| 23178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | ut_a(value != nullptr); |
| 23179 | |||
| 23180 |
1/2✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
|
32 | table_name = value->val_str(value, buff, &len); |
| 23181 | |||
| 23182 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 24 times.
|
32 | if (!table_name) { |
| 23183 | 8 | *static_cast<const char **>(save) = nullptr; | |
| 23184 | 8 | return (0); | |
| 23185 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24 | } else if (table_name == buff) { |
| 23186 | /* Allocate memory from thd's mem_root */ | ||
| 23187 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | table_name = thd_strmake(thd, table_name, len); |
| 23188 | } | ||
| 23189 | |||
| 23190 | /* If name is longer than NAME_LEN, no need to try to open it */ | ||
| 23191 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24 | if (len >= NAME_LEN) { |
| 23192 | 2 | return (1); | |
| 23193 | } | ||
| 23194 | |||
| 23195 | user_table = | ||
| 23196 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | dd_table_open_on_name(thd, &mdl, table_name, false, DICT_ERR_IGNORE_NONE); |
| 23197 | |||
| 23198 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1 times.
|
22 | if (user_table) { |
| 23199 |
3/4✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 1 times.
|
21 | if (dict_table_has_fts_index(user_table)) { |
| 23200 | 20 | *static_cast<const char **>(save) = table_name; | |
| 23201 | 20 | ret = 0; | |
| 23202 | } | ||
| 23203 | |||
| 23204 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | dd_table_close(user_table, thd, &mdl, false); |
| 23205 | |||
| 23206 |
6/10✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
21 | DBUG_EXECUTE_IF("innodb_evict_autoinc_table", dict_sys_mutex_enter(); |
| 23207 | dict_table_remove_from_cache_debug(user_table, true); | ||
| 23208 | dict_sys_mutex_exit();); | ||
| 23209 | } | ||
| 23210 | |||
| 23211 | 22 | return (ret); | |
| 23212 | } | ||
| 23213 | |||
| 23214 | /** Update the system variable innodb_adaptive_hash_index using the "saved" | ||
| 23215 | value. This function is registered as a callback with MySQL. */ | ||
| 23216 | 17 | static void innodb_adaptive_hash_index_update( | |
| 23217 | THD *, /*!< in: thread handle */ | ||
| 23218 | SYS_VAR *, /*!< in: pointer to | ||
| 23219 | system variable */ | ||
| 23220 | void *, /*!< out: where the | ||
| 23221 | formal string goes */ | ||
| 23222 | const void *save) /*!< in: immediate result | ||
| 23223 | from check function */ | ||
| 23224 | { | ||
| 23225 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
|
17 | if (*(bool *)save) { |
| 23226 | 11 | btr_search_enable(true); | |
| 23227 | } else { | ||
| 23228 | 6 | btr_search_disable(true); | |
| 23229 | } | ||
| 23230 | 17 | } | |
| 23231 | |||
| 23232 | /** Update the system variable innodb_cmp_per_index using the "saved" | ||
| 23233 | value. This function is registered as a callback with MySQL. */ | ||
| 23234 | 75 | static void innodb_cmp_per_index_update( | |
| 23235 | THD *, /*!< in: thread handle */ | ||
| 23236 | SYS_VAR *, /*!< in: pointer to | ||
| 23237 | system variable */ | ||
| 23238 | void *, /*!< out: where the | ||
| 23239 | formal string goes */ | ||
| 23240 | const void *save) /*!< in: immediate result | ||
| 23241 | from check function */ | ||
| 23242 | { | ||
| 23243 | /* Reset the stats whenever we enable the table | ||
| 23244 | INFORMATION_SCHEMA.innodb_cmp_per_index. */ | ||
| 23245 |
4/4✓ Branch 0 taken 40 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 4 times.
|
75 | if (!srv_cmp_per_index_enabled && *(bool *)save) { |
| 23246 | 36 | page_zip_reset_stat_per_index(); | |
| 23247 | } | ||
| 23248 | |||
| 23249 | 75 | srv_cmp_per_index_enabled = *(bool *)save; | |
| 23250 | 75 | } | |
| 23251 | |||
| 23252 | /** Update the system variable innodb_old_blocks_pct using the "saved" | ||
| 23253 | value. This function is registered as a callback with MySQL. */ | ||
| 23254 | 11 | static void innodb_old_blocks_pct_update( | |
| 23255 | THD *, /*!< in: thread handle */ | ||
| 23256 | SYS_VAR *, /*!< in: pointer to | ||
| 23257 | system variable */ | ||
| 23258 | void *, /*!< out: where the | ||
| 23259 | formal string goes */ | ||
| 23260 | const void *save) /*!< in: immediate result | ||
| 23261 | from check function */ | ||
| 23262 | { | ||
| 23263 | 11 | innobase_old_blocks_pct = static_cast<uint>( | |
| 23264 | 11 | buf_LRU_old_ratio_update(*static_cast<const uint *>(save), true)); | |
| 23265 | 11 | } | |
| 23266 | |||
| 23267 | /** Update the system variable innodb_old_blocks_pct using the "saved" | ||
| 23268 | value. This function is registered as a callback with MySQL. */ | ||
| 23269 | 12 | static void innodb_change_buffer_max_size_update( | |
| 23270 | THD *, /*!< in: thread handle */ | ||
| 23271 | SYS_VAR *, /*!< in: pointer to | ||
| 23272 | system variable */ | ||
| 23273 | void *, /*!< out: where the | ||
| 23274 | formal string goes */ | ||
| 23275 | const void *save) /*!< in: immediate result | ||
| 23276 | from check function */ | ||
| 23277 | { | ||
| 23278 | 12 | srv_change_buffer_max_size = (*static_cast<const uint *>(save)); | |
| 23279 | 12 | ibuf_max_size_update(srv_change_buffer_max_size); | |
| 23280 | 12 | } | |
| 23281 | |||
| 23282 | #ifdef UNIV_DEBUG | ||
| 23283 | static ulong srv_fil_make_page_dirty_debug = 0; | ||
| 23284 | static ulong srv_saved_page_number_debug = 0; | ||
| 23285 | |||
| 23286 | /** Save an InnoDB page number. */ | ||
| 23287 | 61 | static void innodb_save_page_no(THD *, /*!< in: thread handle */ | |
| 23288 | SYS_VAR *, /*!< in: pointer to | ||
| 23289 | system variable */ | ||
| 23290 | void *, /*!< out: where the | ||
| 23291 | formal string goes */ | ||
| 23292 | const void *save) /*!< in: immediate result | ||
| 23293 | from check function */ | ||
| 23294 | { | ||
| 23295 | 61 | srv_saved_page_number_debug = *static_cast<const ulong *>(save); | |
| 23296 | |||
| 23297 |
1/2✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
|
122 | ib::info(ER_IB_MSG_1257) << "Saving InnoDB page number: " |
| 23298 |
1/2✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
|
61 | << srv_saved_page_number_debug; |
| 23299 | 61 | } | |
| 23300 | |||
| 23301 | /** Make the first page of given user tablespace dirty. */ | ||
| 23302 | 57 | static void innodb_make_page_dirty(THD *, /*!< in: thread handle */ | |
| 23303 | SYS_VAR *, /*!< in: pointer to | ||
| 23304 | system variable */ | ||
| 23305 | void *, /*!< out: where the | ||
| 23306 | formal string goes */ | ||
| 23307 | const void *save) /*!< in: immediate result | ||
| 23308 | from check function */ | ||
| 23309 | { | ||
| 23310 |
1/2✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
|
57 | mtr_t mtr; |
| 23311 | 57 | ulong space_id = *static_cast<const ulong *>(save); | |
| 23312 | 57 | page_no_t page_no = srv_saved_page_number_debug; | |
| 23313 | |||
| 23314 |
1/2✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
|
57 | fil_space_t *space = fil_space_acquire_silent(space_id); |
| 23315 | |||
| 23316 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 52 times.
|
57 | if (space == nullptr) { |
| 23317 | 5 | return; | |
| 23318 | } | ||
| 23319 | |||
| 23320 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
|
52 | if (page_no > space->size) { |
| 23321 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | fil_space_release(space); |
| 23322 | 2 | return; | |
| 23323 | } | ||
| 23324 | |||
| 23325 | 50 | auto page_id = page_id_t{space->id, page_no}; | |
| 23326 | |||
| 23327 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | mtr.start(); |
| 23328 | |||
| 23329 |
2/4✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
50 | buf_block_t *block = buf_page_get(page_id, page_size_t(space->flags), |
| 23330 | RW_X_LATCH, UT_LOCATION_HERE, &mtr); | ||
| 23331 | |||
| 23332 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | if (block != nullptr) { |
| 23333 | 50 | byte *page = block->frame; | |
| 23334 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | page_type_t page_type = fil_page_get_type(page); |
| 23335 | |||
| 23336 | /* Don't dirty a page that is not yet used. */ | ||
| 23337 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 1 times.
|
50 | if (page_type != FIL_PAGE_TYPE_ALLOCATED) { |
| 23338 |
1/2✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
|
49 | ib::info(ER_IB_MSG_574) |
| 23339 |
2/4✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
|
49 | << "Dirtying page: " << page_id |
| 23340 |
2/4✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
|
49 | << ", page_type=" << fil_get_page_type_str(page_type); |
| 23341 | |||
| 23342 | 49 | dblwr::Force_crash = page_id; | |
| 23343 | |||
| 23344 |
1/2✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
|
49 | mlog_write_ulint(page + FIL_PAGE_TYPE, page_type, MLOG_2BYTES, &mtr); |
| 23345 | } | ||
| 23346 | } | ||
| 23347 | |||
| 23348 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | mtr.commit(); |
| 23349 | |||
| 23350 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | fil_space_release(space); |
| 23351 | |||
| 23352 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | if (block != nullptr) { |
| 23353 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
50 | buf_flush_sync_all_buf_pools(); |
| 23354 | } | ||
| 23355 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
|
9 | } |
| 23356 | #endif // UNIV_DEBUG | ||
| 23357 | |||
| 23358 | /** Update the monitor counter according to the "set_option", turn | ||
| 23359 | on/off or reset specified monitor counter. */ | ||
| 23360 | 9556 | static void innodb_monitor_set_option( | |
| 23361 | const monitor_info_t *monitor_info, /*!< in: monitor info for the monitor | ||
| 23362 | to set */ | ||
| 23363 | mon_option_t set_option) /*!< in: Turn on/off reset the | ||
| 23364 | counter */ | ||
| 23365 | { | ||
| 23366 | 9556 | monitor_id_t monitor_id = monitor_info->monitor_id; | |
| 23367 | |||
| 23368 | /* If module type is MONITOR_GROUP_MODULE, it cannot be | ||
| 23369 | turned on/off individually. It should never use this | ||
| 23370 | function to set options */ | ||
| 23371 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9556 times.
|
9556 | ut_a(!(monitor_info->monitor_type & MONITOR_GROUP_MODULE)); |
| 23372 | |||
| 23373 |
4/5✓ Branch 0 taken 5905 times.
✓ Branch 1 taken 3316 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 294 times.
✗ Branch 4 not taken.
|
9556 | switch (set_option) { |
| 23374 | 5905 | case MONITOR_TURN_ON: | |
| 23375 | 5905 | MONITOR_ON(monitor_id); | |
| 23376 |
4/6✓ Branch 0 taken 14 times.
✓ Branch 1 taken 5891 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
|
5905 | MONITOR_INIT(monitor_id); |
| 23377 | 5905 | MONITOR_SET_START(monitor_id); | |
| 23378 | |||
| 23379 | /* If the monitor to be turned on uses | ||
| 23380 | existing monitor counter (status variable), | ||
| 23381 | make special processing to remember existing | ||
| 23382 | counter value. */ | ||
| 23383 |
2/2✓ Branch 0 taken 3085 times.
✓ Branch 1 taken 2820 times.
|
5905 | if (monitor_info->monitor_type & MONITOR_EXISTING) { |
| 23384 | 3085 | srv_mon_process_existing_counter(monitor_id, MONITOR_TURN_ON); | |
| 23385 | } | ||
| 23386 | |||
| 23387 |
2/2✓ Branch 0 taken 189 times.
✓ Branch 1 taken 5716 times.
|
5905 | if (MONITOR_IS_ON(MONITOR_LATCHES)) { |
| 23388 | 189 | mutex_monitor->enable(); | |
| 23389 | } | ||
| 23390 | 5905 | break; | |
| 23391 | |||
| 23392 | 3316 | case MONITOR_TURN_OFF: | |
| 23393 |
2/2✓ Branch 0 taken 988 times.
✓ Branch 1 taken 2328 times.
|
3316 | if (monitor_info->monitor_type & MONITOR_EXISTING) { |
| 23394 | 988 | srv_mon_process_existing_counter(monitor_id, MONITOR_TURN_OFF); | |
| 23395 | } | ||
| 23396 | |||
| 23397 | 3316 | MONITOR_OFF(monitor_id); | |
| 23398 | 3316 | MONITOR_SET_OFF(monitor_id); | |
| 23399 | |||
| 23400 |
2/2✓ Branch 0 taken 401 times.
✓ Branch 1 taken 2915 times.
|
3316 | if (!MONITOR_IS_ON(MONITOR_LATCHES)) { |
| 23401 | 401 | mutex_monitor->disable(); | |
| 23402 | } | ||
| 23403 | 3316 | break; | |
| 23404 | |||
| 23405 | 41 | case MONITOR_RESET_VALUE: | |
| 23406 | 41 | srv_mon_reset(monitor_id); | |
| 23407 | |||
| 23408 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 39 times.
|
41 | if (monitor_id == (MONITOR_LATCHES)) { |
| 23409 | 2 | mutex_monitor->reset(); | |
| 23410 | } | ||
| 23411 | 41 | break; | |
| 23412 | |||
| 23413 | 294 | case MONITOR_RESET_ALL_VALUE: | |
| 23414 | 294 | srv_mon_reset_all(monitor_id); | |
| 23415 | 294 | mutex_monitor->reset(); | |
| 23416 | 294 | break; | |
| 23417 | |||
| 23418 | ✗ | default: | |
| 23419 | ✗ | ut_error; | |
| 23420 | } | ||
| 23421 | 9556 | } | |
| 23422 | |||
| 23423 | /** Find matching InnoDB monitor counters and update their status | ||
| 23424 | according to the "set_option", turn on/off or reset specified | ||
| 23425 | monitor counter. */ | ||
| 23426 | 53 | static void innodb_monitor_update_wildcard( | |
| 23427 | const char *name, /*!< in: monitor name to match */ | ||
| 23428 | mon_option_t set_option) /*!< in: the set option, whether | ||
| 23429 | to turn on/off or reset the counter */ | ||
| 23430 | { | ||
| 23431 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | ut_a(name); |
| 23432 | |||
| 23433 |
2/2✓ Branch 0 taken 18126 times.
✓ Branch 1 taken 53 times.
|
18179 | for (ulint use = 0; use < NUM_MONITOR; use++) { |
| 23434 | ulint type; | ||
| 23435 | 18126 | monitor_id_t monitor_id = static_cast<monitor_id_t>(use); | |
| 23436 | monitor_info_t *monitor_info; | ||
| 23437 | |||
| 23438 |
2/2✓ Branch 0 taken 8541 times.
✓ Branch 1 taken 9585 times.
|
18126 | if (!innobase_wildcasecmp(srv_mon_get_name(monitor_id), name)) { |
| 23439 | 8541 | monitor_info = srv_mon_get_info(monitor_id); | |
| 23440 | |||
| 23441 | 8541 | type = monitor_info->monitor_type; | |
| 23442 | |||
| 23443 | /* If the monitor counter is of MONITOR_MODULE | ||
| 23444 | type, skip it. Except for those also marked with | ||
| 23445 | MONITOR_GROUP_MODULE flag, which can be turned | ||
| 23446 | on only as a module. */ | ||
| 23447 |
4/4✓ Branch 0 taken 8002 times.
✓ Branch 1 taken 539 times.
✓ Branch 2 taken 7151 times.
✓ Branch 3 taken 851 times.
|
8541 | if (!(type & MONITOR_MODULE) && !(type & MONITOR_GROUP_MODULE)) { |
| 23448 | 7151 | innodb_monitor_set_option(monitor_info, set_option); | |
| 23449 | } | ||
| 23450 | |||
| 23451 | /* Need to special handle counters marked with | ||
| 23452 | MONITOR_GROUP_MODULE, turn on the whole module if | ||
| 23453 | any one of it comes here. Currently, only | ||
| 23454 | "module_buf_page" is marked with MONITOR_GROUP_MODULE */ | ||
| 23455 |
2/2✓ Branch 0 taken 874 times.
✓ Branch 1 taken 7667 times.
|
8541 | if (type & MONITOR_GROUP_MODULE) { |
| 23456 |
1/2✓ Branch 0 taken 874 times.
✗ Branch 1 not taken.
|
874 | if ((monitor_id >= MONITOR_MODULE_BUF_PAGE) && |
| 23457 |
1/2✓ Branch 0 taken 874 times.
✗ Branch 1 not taken.
|
874 | (monitor_id < MONITOR_MODULE_OS)) { |
| 23458 |
2/2✓ Branch 0 taken 418 times.
✓ Branch 1 taken 456 times.
|
874 | if (set_option == MONITOR_TURN_ON && |
| 23459 |
2/2✓ Branch 0 taken 407 times.
✓ Branch 1 taken 11 times.
|
418 | MONITOR_IS_ON(MONITOR_MODULE_BUF_PAGE)) { |
| 23460 | 407 | continue; | |
| 23461 | } | ||
| 23462 | |||
| 23463 | 467 | srv_mon_set_module_control(MONITOR_MODULE_BUF_PAGE, set_option); | |
| 23464 | } else { | ||
| 23465 | /* If new monitor is added with | ||
| 23466 | MONITOR_GROUP_MODULE, it needs | ||
| 23467 | to be added here. */ | ||
| 23468 | ✗ | ut_d(ut_error); | |
| 23469 | } | ||
| 23470 | } | ||
| 23471 | } | ||
| 23472 | } | ||
| 23473 | 53 | } | |
| 23474 | |||
| 23475 | /** Given a configuration variable name, find corresponding monitor counter | ||
| 23476 | and return its monitor ID if found. | ||
| 23477 | @return monitor ID if found, MONITOR_NO_MATCH if there is no match */ | ||
| 23478 | 5406 | static ulint innodb_monitor_id_by_name_get( | |
| 23479 | const char *name) /*!< in: monitor counter namer */ | ||
| 23480 | { | ||
| 23481 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5406 times.
|
5406 | ut_a(name); |
| 23482 | |||
| 23483 | /* Search for wild character '%' in the name, if | ||
| 23484 | found, we treat it as a wildcard match. We do not search for | ||
| 23485 | single character wildcard '_' since our monitor names already contain | ||
| 23486 | such character. To avoid confusion, we request user must include | ||
| 23487 | at least one '%' character to activate the wildcard search. */ | ||
| 23488 |
2/2✓ Branch 0 taken 111 times.
✓ Branch 1 taken 5295 times.
|
5406 | if (strchr(name, '%')) { |
| 23489 | 111 | return (MONITOR_WILDCARD_MATCH); | |
| 23490 | } | ||
| 23491 | |||
| 23492 | /* Not wildcard match, check for an exact match */ | ||
| 23493 |
2/2✓ Branch 0 taken 899350 times.
✓ Branch 1 taken 15 times.
|
899365 | for (ulint i = 0; i < NUM_MONITOR; i++) { |
| 23494 |
2/2✓ Branch 0 taken 5280 times.
✓ Branch 1 taken 894070 times.
|
899350 | if (!innobase_strcasecmp(name, |
| 23495 | srv_mon_get_name(static_cast<monitor_id_t>(i)))) { | ||
| 23496 | 5280 | return (i); | |
| 23497 | } | ||
| 23498 | } | ||
| 23499 | |||
| 23500 | 15 | return (MONITOR_NO_MATCH); | |
| 23501 | } | ||
| 23502 | /** Validate that the passed in monitor name matches at least one | ||
| 23503 | monitor counter name with wildcard compare. | ||
| 23504 | @return true if at least one monitor name matches */ | ||
| 23505 | 58 | static bool innodb_monitor_validate_wildcard_name( | |
| 23506 | const char *name) /*!< in: monitor counter namer */ | ||
| 23507 | { | ||
| 23508 |
2/2✓ Branch 0 taken 5833 times.
✓ Branch 1 taken 5 times.
|
5838 | for (ulint i = 0; i < NUM_MONITOR; i++) { |
| 23509 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 5780 times.
|
5833 | if (!innobase_wildcasecmp(srv_mon_get_name(static_cast<monitor_id_t>(i)), |
| 23510 | name)) { | ||
| 23511 | 53 | return true; | |
| 23512 | } | ||
| 23513 | } | ||
| 23514 | |||
| 23515 | 5 | return false; | |
| 23516 | } | ||
| 23517 | /** Validate the passed in monitor name, find and save the | ||
| 23518 | corresponding monitor name in the function parameter "save". | ||
| 23519 | @return 0 if monitor name is valid */ | ||
| 23520 | 2713 | static int innodb_monitor_valid_byname( | |
| 23521 | void *save, /*!< out: immediate result | ||
| 23522 | for update function */ | ||
| 23523 | const char *name) /*!< in: incoming monitor name */ | ||
| 23524 | { | ||
| 23525 | ulint use; | ||
| 23526 | monitor_info_t *monitor_info; | ||
| 23527 | |||
| 23528 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2713 times.
|
2713 | if (!name) { |
| 23529 | ✗ | return (1); | |
| 23530 | } | ||
| 23531 | |||
| 23532 | 2713 | use = innodb_monitor_id_by_name_get(name); | |
| 23533 | |||
| 23534 | /* No monitor name matches, nor it is wildcard match */ | ||
| 23535 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2698 times.
|
2713 | if (use == MONITOR_NO_MATCH) { |
| 23536 | 15 | return (1); | |
| 23537 | } | ||
| 23538 | |||
| 23539 |
2/2✓ Branch 0 taken 2640 times.
✓ Branch 1 taken 58 times.
|
2698 | if (use < NUM_MONITOR) { |
| 23540 | 2640 | monitor_info = srv_mon_get_info((monitor_id_t)use); | |
| 23541 | |||
| 23542 | /* If the monitor counter is marked with | ||
| 23543 | MONITOR_GROUP_MODULE flag, then this counter | ||
| 23544 | cannot be turned on/off individually, instead | ||
| 23545 | it shall be turned on/off as a group using | ||
| 23546 | its module name */ | ||
| 23547 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2636 times.
|
2640 | if ((monitor_info->monitor_type & MONITOR_GROUP_MODULE) && |
| 23548 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | (!(monitor_info->monitor_type & MONITOR_MODULE))) { |
| 23549 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_USE_MONITOR_GROUP_NAME, name); | |
| 23550 | ✗ | return (1); | |
| 23551 | } | ||
| 23552 | |||
| 23553 | } else { | ||
| 23554 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | ut_a(use == MONITOR_WILDCARD_MATCH); |
| 23555 | |||
| 23556 | /* For wildcard match, if there is not a single monitor | ||
| 23557 | counter name that matches, treat it as an invalid | ||
| 23558 | value for the system configuration variables */ | ||
| 23559 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 53 times.
|
58 | if (!innodb_monitor_validate_wildcard_name(name)) { |
| 23560 | 5 | return (1); | |
| 23561 | } | ||
| 23562 | } | ||
| 23563 | |||
| 23564 | /* Save the configure name for innodb_monitor_update() */ | ||
| 23565 | 2693 | *static_cast<const char **>(save) = name; | |
| 23566 | |||
| 23567 | 2693 | return (0); | |
| 23568 | } | ||
| 23569 | /** Validate passed-in "value" is a valid monitor counter name. | ||
| 23570 | This function is registered as a callback with MySQL. | ||
| 23571 | @return 0 for valid name */ | ||
| 23572 | 2719 | static int innodb_monitor_validate( | |
| 23573 | THD *, /*!< in: thread handle */ | ||
| 23574 | SYS_VAR *, /*!< in: pointer to system | ||
| 23575 | variable */ | ||
| 23576 | void *save, /*!< out: immediate result | ||
| 23577 | for update function */ | ||
| 23578 | struct st_mysql_value *value) /*!< in: incoming string */ | ||
| 23579 | { | ||
| 23580 | const char *name; | ||
| 23581 | char *monitor_name; | ||
| 23582 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 23583 | 2719 | int len = sizeof(buff); | |
| 23584 | int ret; | ||
| 23585 | |||
| 23586 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2719 times.
|
2719 | ut_a(save != nullptr); |
| 23587 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2719 times.
|
2719 | ut_a(value != nullptr); |
| 23588 | |||
| 23589 |
1/2✓ Branch 0 taken 2719 times.
✗ Branch 1 not taken.
|
2719 | name = value->val_str(value, buff, &len); |
| 23590 | |||
| 23591 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2715 times.
|
2719 | if (name == nullptr) { |
| 23592 | 4 | return (1); | |
| 23593 | } | ||
| 23594 | |||
| 23595 | /* Check if the value is a valid string. */ | ||
| 23596 | size_t valid_len; | ||
| 23597 | bool len_error; | ||
| 23598 |
3/4✓ Branch 0 taken 2715 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2711 times.
|
2715 | if (validate_string(system_charset_info, name, len, &valid_len, &len_error)) { |
| 23599 | 4 | return (1); | |
| 23600 | } | ||
| 23601 | |||
| 23602 | /* monitor_name could point to memory from MySQL | ||
| 23603 | or buff[]. Always dup the name to memory allocated | ||
| 23604 | by InnoDB, so we can access it in another callback | ||
| 23605 | function innodb_monitor_update() and free it appropriately */ | ||
| 23606 |
1/2✓ Branch 0 taken 2711 times.
✗ Branch 1 not taken.
|
2711 | if (name) { |
| 23607 |
1/2✓ Branch 0 taken 2711 times.
✗ Branch 1 not taken.
|
2711 | monitor_name = my_strdup(PSI_INSTRUMENT_ME, name, MYF(0)); |
| 23608 | } else { | ||
| 23609 | ✗ | return (1); | |
| 23610 | } | ||
| 23611 | |||
| 23612 |
1/2✓ Branch 0 taken 2711 times.
✗ Branch 1 not taken.
|
2711 | ret = innodb_monitor_valid_byname(save, monitor_name); |
| 23613 | |||
| 23614 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2691 times.
|
2711 | if (ret) { |
| 23615 | /* Validation failed */ | ||
| 23616 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | my_free(monitor_name); |
| 23617 | } else { | ||
| 23618 | /* monitor_name will be freed in separate callback function | ||
| 23619 | innodb_monitor_update(). Assert "save" point to | ||
| 23620 | the "monitor_name" variable */ | ||
| 23621 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2691 times.
|
2691 | ut_ad(*static_cast<char **>(save) == monitor_name); |
| 23622 | } | ||
| 23623 | |||
| 23624 | 2711 | return (ret); | |
| 23625 | } | ||
| 23626 | |||
| 23627 | /** Update the system variable innodb_enable(disable/reset/reset_all)_monitor | ||
| 23628 | according to the "set_option" and turn on/off or reset specified monitor | ||
| 23629 | counter. */ | ||
| 23630 | 2815 | static void innodb_monitor_update( | |
| 23631 | THD *thd, /*!< in: thread handle */ | ||
| 23632 | void *var_ptr, /*!< out: where the | ||
| 23633 | formal string goes */ | ||
| 23634 | const void *save, /*!< in: immediate result | ||
| 23635 | from check function */ | ||
| 23636 | mon_option_t set_option, /*!< in: the set option, | ||
| 23637 | whether to turn on/off or | ||
| 23638 | reset the counter */ | ||
| 23639 | bool free_mem) /*!< in: whether we will | ||
| 23640 | need to free the memory */ | ||
| 23641 | { | ||
| 23642 | monitor_info_t *monitor_info; | ||
| 23643 | ulint monitor_id; | ||
| 23644 | 2815 | ulint err_monitor = 0; | |
| 23645 | const char *name; | ||
| 23646 | |||
| 23647 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2815 times.
|
2815 | ut_a(save != nullptr); |
| 23648 | |||
| 23649 | 2815 | name = *static_cast<const char *const *>(save); | |
| 23650 | |||
| 23651 |
2/2✓ Branch 0 taken 122 times.
✓ Branch 1 taken 2693 times.
|
2815 | if (!name) { |
| 23652 | 122 | monitor_id = MONITOR_DEFAULT_START; | |
| 23653 | } else { | ||
| 23654 | 2693 | monitor_id = innodb_monitor_id_by_name_get(name); | |
| 23655 | |||
| 23656 | /* Double check we have a valid monitor ID */ | ||
| 23657 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2693 times.
|
2693 | if (monitor_id == MONITOR_NO_MATCH) { |
| 23658 | ✗ | return; | |
| 23659 | } | ||
| 23660 | } | ||
| 23661 | |||
| 23662 |
2/2✓ Branch 0 taken 122 times.
✓ Branch 1 taken 2693 times.
|
2815 | if (monitor_id == MONITOR_DEFAULT_START) { |
| 23663 | /* If user set the variable to "default", we will | ||
| 23664 | print a message and make this set operation a "noop". | ||
| 23665 | The check is being made here is because "set default" | ||
| 23666 | does not go through validation function */ | ||
| 23667 |
1/2✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
|
122 | if (thd) { |
| 23668 | 122 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_DEFAULT, | |
| 23669 | "Default value is not defined for" | ||
| 23670 | " this set option. Please specify" | ||
| 23671 | " correct counter or module name."); | ||
| 23672 | } else { | ||
| 23673 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_MONITOR_DEFAULT_VALUE_NOT_DEFINED); | |
| 23674 | } | ||
| 23675 | |||
| 23676 |
1/2✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
|
122 | if (var_ptr) { |
| 23677 | 122 | *(const char **)var_ptr = nullptr; | |
| 23678 | } | ||
| 23679 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2640 times.
|
2693 | } else if (monitor_id == MONITOR_WILDCARD_MATCH) { |
| 23680 | 53 | innodb_monitor_update_wildcard(name, set_option); | |
| 23681 | } else { | ||
| 23682 | 2640 | monitor_info = srv_mon_get_info(static_cast<monitor_id_t>(monitor_id)); | |
| 23683 | |||
| 23684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2640 times.
|
2640 | ut_a(monitor_info); |
| 23685 | |||
| 23686 | /* If monitor is already truned on, someone could already | ||
| 23687 | collect monitor data, exit and ask user to turn off the | ||
| 23688 | monitor before turn it on again. */ | ||
| 23689 |
4/4✓ Branch 0 taken 2355 times.
✓ Branch 1 taken 285 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2351 times.
|
2640 | if (set_option == MONITOR_TURN_ON && MONITOR_IS_ON(monitor_id)) { |
| 23690 | 4 | err_monitor = monitor_id; | |
| 23691 | 4 | goto exit; | |
| 23692 | } | ||
| 23693 | |||
| 23694 |
2/2✓ Branch 0 taken 2634 times.
✓ Branch 1 taken 2 times.
|
2636 | if (var_ptr) { |
| 23695 | 2634 | *(const char **)var_ptr = monitor_info->monitor_name; | |
| 23696 | } | ||
| 23697 | |||
| 23698 | /* Depending on the monitor name is for a module or | ||
| 23699 | a counter, process counters in the whole module or | ||
| 23700 | individual counter. */ | ||
| 23701 |
2/2✓ Branch 0 taken 231 times.
✓ Branch 1 taken 2405 times.
|
2636 | if (monitor_info->monitor_type & MONITOR_MODULE) { |
| 23702 | 231 | srv_mon_set_module_control(static_cast<monitor_id_t>(monitor_id), | |
| 23703 | set_option); | ||
| 23704 | } else { | ||
| 23705 | 2405 | innodb_monitor_set_option(monitor_info, set_option); | |
| 23706 | } | ||
| 23707 | } | ||
| 23708 | 2815 | exit: | |
| 23709 | /* Only if we are trying to turn on a monitor that already | ||
| 23710 | been turned on, we will set err_monitor. Print related | ||
| 23711 | information */ | ||
| 23712 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2811 times.
|
2815 | if (err_monitor) { |
| 23713 | 4 | log_errlog(WARNING_LEVEL, ER_INNODB_MONITOR_IS_ENABLED, | |
| 23714 | srv_mon_get_name((monitor_id_t)err_monitor)); | ||
| 23715 | } | ||
| 23716 | |||
| 23717 |
4/4✓ Branch 0 taken 2813 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2691 times.
✓ Branch 3 taken 122 times.
|
2815 | if (free_mem && name) { |
| 23718 | 2691 | my_free((void *)name); | |
| 23719 | } | ||
| 23720 | |||
| 23721 | 2815 | return; | |
| 23722 | } | ||
| 23723 | |||
| 23724 | /** Validate if passed-in "value" is a valid value for | ||
| 23725 | innodb_buffer_pool_filename. On Windows, file names with colon (:) | ||
| 23726 | are not allowed. | ||
| 23727 | @param[in] thd thread handle | ||
| 23728 | @param[in] save immediate result from update function | ||
| 23729 | @param[in] value incoming string | ||
| 23730 | @return 0 for valid name */ | ||
| 23731 | 9 | static int innodb_srv_buf_dump_filename_validate(THD *thd, SYS_VAR *, | |
| 23732 | void *save, | ||
| 23733 | struct st_mysql_value *value) { | ||
| 23734 | char buff[OS_FILE_MAX_PATH]; | ||
| 23735 | 9 | int len = sizeof(buff); | |
| 23736 | |||
| 23737 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | ut_a(save != nullptr); |
| 23738 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | ut_a(value != nullptr); |
| 23739 | |||
| 23740 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | const char *buf_name = value->val_str(value, buff, &len); |
| 23741 | |||
| 23742 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (buf_name == nullptr) { |
| 23743 | ✗ | return (1); | |
| 23744 | } | ||
| 23745 | |||
| 23746 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
|
9 | if (buf_name == buff) { |
| 23747 | /* Allocate from thd's memroot */ | ||
| 23748 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | buf_name = thd_strmake(thd, buf_name, len); |
| 23749 | } | ||
| 23750 | |||
| 23751 | #ifdef _WIN32 | ||
| 23752 | if (is_filename_allowed(buf_name, len, false)) { | ||
| 23753 | *static_cast<const char **>(save) = buf_name; | ||
| 23754 | return (0); | ||
| 23755 | } else { | ||
| 23756 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | ||
| 23757 | "InnoDB: innodb_buffer_pool_filename" | ||
| 23758 | " cannot have colon (:) in the file name."); | ||
| 23759 | return (1); | ||
| 23760 | } | ||
| 23761 | #else /* _WIN32 */ | ||
| 23762 | 9 | *static_cast<const char **>(save) = buf_name; | |
| 23763 | 9 | return (0); | |
| 23764 | #endif | ||
| 23765 | } | ||
| 23766 | |||
| 23767 | #ifdef UNIV_DEBUG | ||
| 23768 | static char *srv_buffer_pool_evict; | ||
| 23769 | |||
| 23770 | /** Evict all uncompressed pages of compressed tables from the buffer pool. | ||
| 23771 | Keep the compressed pages in the buffer pool. | ||
| 23772 | @return whether all uncompressed pages were evicted */ | ||
| 23773 | 1847 | [[nodiscard]] static bool innodb_buffer_pool_evict_uncompressed(void) { | |
| 23774 | 1847 | bool all_evicted = true; | |
| 23775 | |||
| 23776 |
2/2✓ Branch 0 taken 1847 times.
✓ Branch 1 taken 1847 times.
|
3694 | for (ulint i = 0; i < srv_buf_pool_instances; i++) { |
| 23777 | 1847 | buf_pool_t *buf_pool = &buf_pool_ptr[i]; | |
| 23778 | |||
| 23779 | 1847 | mutex_enter(&buf_pool->LRU_list_mutex); | |
| 23780 | |||
| 23781 | 1847 | for (buf_block_t *block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); | |
| 23782 |
2/2✓ Branch 0 taken 4855 times.
✓ Branch 1 taken 1847 times.
|
6702 | block != nullptr;) { |
| 23783 | 4855 | buf_block_t *prev_block = UT_LIST_GET_PREV(unzip_LRU, block); | |
| 23784 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4855 times.
|
4855 | ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); |
| 23785 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4855 times.
|
4855 | ut_ad(block->in_unzip_LRU_list); |
| 23786 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4855 times.
|
4855 | ut_ad(block->page.in_LRU_list); |
| 23787 | |||
| 23788 | 4855 | mutex_enter(&block->mutex); | |
| 23789 | |||
| 23790 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4839 times.
|
4855 | if (!buf_LRU_free_page(&block->page, false)) { |
| 23791 | 16 | mutex_exit(&block->mutex); | |
| 23792 | 16 | all_evicted = false; | |
| 23793 | } else { | ||
| 23794 | /* buf_LRU_free_page() released LRU_list_mutex. | ||
| 23795 | have to restart the unzip_LRU scan. */ | ||
| 23796 | 4839 | mutex_enter(&buf_pool->LRU_list_mutex); | |
| 23797 | 4839 | block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); | |
| 23798 | 4839 | continue; | |
| 23799 | } | ||
| 23800 | 16 | block = prev_block; | |
| 23801 | } | ||
| 23802 | |||
| 23803 | 1847 | mutex_exit(&buf_pool->LRU_list_mutex); | |
| 23804 | } | ||
| 23805 | |||
| 23806 | 1847 | return (all_evicted); | |
| 23807 | } | ||
| 23808 | |||
| 23809 | /** Called on SET GLOBAL innodb_buffer_pool_evict=... | ||
| 23810 | Handles some values specially, to evict pages from the buffer pool. | ||
| 23811 | SET GLOBAL innodb_buffer_pool_evict='uncompressed' | ||
| 23812 | evicts all uncompressed page frames of compressed tablespaces. | ||
| 23813 | @param[in] save immediate result from check function */ | ||
| 23814 | 1845 | static void innodb_buffer_pool_evict_update(THD *, SYS_VAR *, void *, | |
| 23815 | const void *save) { | ||
| 23816 |
2/2✓ Branch 0 taken 1844 times.
✓ Branch 1 taken 1 times.
|
1845 | if (const char *op = *static_cast<const char *const *>(save)) { |
| 23817 |
2/2✓ Branch 0 taken 1841 times.
✓ Branch 1 taken 3 times.
|
1844 | if (!strcmp(op, "uncompressed")) { |
| 23818 |
1/2✓ Branch 0 taken 1847 times.
✗ Branch 1 not taken.
|
1847 | for (uint tries = 0; tries < 10000; tries++) { |
| 23819 |
2/2✓ Branch 0 taken 1841 times.
✓ Branch 1 taken 6 times.
|
1847 | if (innodb_buffer_pool_evict_uncompressed()) { |
| 23820 | 1841 | return; | |
| 23821 | } | ||
| 23822 | |||
| 23823 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
| 23824 | } | ||
| 23825 | |||
| 23826 | /* We failed to evict all uncompressed pages. */ | ||
| 23827 | ✗ | ut_d(ut_error); | |
| 23828 | } | ||
| 23829 | } | ||
| 23830 | } | ||
| 23831 | #endif /* UNIV_DEBUG */ | ||
| 23832 | |||
| 23833 | /** Update the system variable innodb_monitor_enable and enable | ||
| 23834 | specified monitor counter. | ||
| 23835 | This function is registered as a callback with MySQL. | ||
| 23836 | @param[in] thd thread handle | ||
| 23837 | @param[out] var_ptr where the formal string goes | ||
| 23838 | @param[in] save immediate result from check function */ | ||
| 23839 | 2419 | static void innodb_enable_monitor_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 23840 | const void *save) { | ||
| 23841 | 2419 | innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_ON, true); | |
| 23842 | 2419 | } | |
| 23843 | |||
| 23844 | /** Update the system variable innodb_monitor_disable and turn | ||
| 23845 | off specified monitor counter. | ||
| 23846 | @param[in] thd thread handle | ||
| 23847 | @param[out] var_ptr where the formal string goes | ||
| 23848 | @param[in] save immediate result from check function */ | ||
| 23849 | 179 | static void innodb_disable_monitor_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 23850 | const void *save) { | ||
| 23851 | 179 | innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_OFF, true); | |
| 23852 | 179 | } | |
| 23853 | |||
| 23854 | /** Update the system variable innodb_monitor_reset and reset | ||
| 23855 | specified monitor counter(s). | ||
| 23856 | This function is registered as a callback with MySQL. | ||
| 23857 | @param[in] thd thread handle | ||
| 23858 | @param[out] var_ptr where the formal string goes | ||
| 23859 | @param[in] save immediate result from check function */ | ||
| 23860 | 123 | static void innodb_reset_monitor_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 23861 | const void *save) { | ||
| 23862 | 123 | innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_VALUE, true); | |
| 23863 | 123 | } | |
| 23864 | |||
| 23865 | /** Update the system variable innodb_monitor_reset_all and reset | ||
| 23866 | all value related monitor counter. | ||
| 23867 | This function is registered as a callback with MySQL. | ||
| 23868 | @param[in] thd thread handle | ||
| 23869 | @param[out] var_ptr where the formal string goes | ||
| 23870 | @param[in] save immediate result from check function */ | ||
| 23871 | 92 | static void innodb_reset_all_monitor_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 23872 | const void *save) { | ||
| 23873 | 92 | innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_ALL_VALUE, true); | |
| 23874 | 92 | } | |
| 23875 | |||
| 23876 | /** Validate the value of innodb_undo_tablespaces global variable. This function | ||
| 23877 | is registered as a callback with MySQL. | ||
| 23878 | @param[in] thd thread handle | ||
| 23879 | @param[in] var pointer to system variable | ||
| 23880 | @param[in] var_ptr where the formal string goes | ||
| 23881 | @param[in] save immediate result from check function */ | ||
| 23882 | 6 | static void innodb_undo_tablespaces_update(THD *thd [[maybe_unused]], | |
| 23883 | SYS_VAR *var [[maybe_unused]], | ||
| 23884 | void *var_ptr [[maybe_unused]], | ||
| 23885 | const void *save [[maybe_unused]]) { | ||
| 23886 | 6 | innodb_undo_tablespaces_deprecate(); | |
| 23887 | 6 | } | |
| 23888 | |||
| 23889 | /** Validate the value of innodb_parallel_doublewrite_path global variable. | ||
| 23890 | This function is registered as a callback with MySQL. | ||
| 23891 | @param[in] thd thread handle | ||
| 23892 | @param[in] var pointer to system variable | ||
| 23893 | @param[in] var_ptr where the formal string goes | ||
| 23894 | @param[in] save immediate result from check function */ | ||
| 23895 | ✗ | static void innodb_parallel_doublewrite_path_update( | |
| 23896 | THD *thd [[maybe_unused]], SYS_VAR *var [[maybe_unused]], | ||
| 23897 | void *var_ptr [[maybe_unused]], | ||
| 23898 | const void *save [[maybe_unused]]) { | ||
| 23899 | ✗ | innodb_parallel_doublewrite_path_deprecate(); | |
| 23900 | } | ||
| 23901 | |||
| 23902 | /** Validate the value of innodb_parallel_dblwr_encrypt global variable. | ||
| 23903 | This function is registered as a callback with MySQL. | ||
| 23904 | @param[in] thd thread handle | ||
| 23905 | @param[in] var pointer to system variable | ||
| 23906 | @param[in] var_ptr where the formal string goes | ||
| 23907 | @param[in] save immediate result from check function */ | ||
| 23908 | 3 | static void innodb_parallel_dblwr_encrypt_update( | |
| 23909 | THD *thd [[maybe_unused]], SYS_VAR *var [[maybe_unused]], | ||
| 23910 | void *var_ptr [[maybe_unused]], | ||
| 23911 | const void *save [[maybe_unused]]) { | ||
| 23912 | 3 | innodb_parallel_dblwr_encrypt_deprecate(); | |
| 23913 | 3 | } | |
| 23914 | |||
| 23915 | /* Declare default check function for boolean system variable. Cannot include | ||
| 23916 | sql_plugin_var.h header in this file due to conflicting macro definitions. */ | ||
| 23917 | int check_func_bool(THD *, SYS_VAR *, void *save, st_mysql_value *value); | ||
| 23918 | |||
| 23919 | /** Validate the value of innodb_undo_log_encrypt global variable. This function | ||
| 23920 | is registered as a callback with MySQL. | ||
| 23921 | @param[in] thd thread handle | ||
| 23922 | @param[in] var pointer to system variable | ||
| 23923 | @param[in] save possibly updated variable value | ||
| 23924 | @param[in] value current variable value | ||
| 23925 | @return error code */ | ||
| 23926 | 105 | static int validate_innodb_undo_log_encrypt(THD *thd, SYS_VAR *var, void *save, | |
| 23927 | struct st_mysql_value *value) { | ||
| 23928 | /* Call the default check function first. */ | ||
| 23929 | 105 | auto error = check_func_bool(thd, var, save, value); | |
| 23930 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 102 times.
|
105 | if (error != 0) { |
| 23931 | 3 | return (error); | |
| 23932 | } | ||
| 23933 | 102 | bool target = *static_cast<bool *>(save); | |
| 23934 | |||
| 23935 | /* Set the default output to current value for all error cases. */ | ||
| 23936 | 102 | *static_cast<bool *>(save) = srv_undo_log_encrypt; | |
| 23937 | |||
| 23938 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 57 times.
|
102 | if (srv_undo_log_encrypt == target) { |
| 23939 | /* No change */ | ||
| 23940 | 45 | return (0); | |
| 23941 | } | ||
| 23942 | |||
| 23943 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 13 times.
|
57 | if (target) { |
| 23944 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
|
44 | if (Encryption::is_online_encryption_on()) { |
| 23945 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23946 | "Undo log cannot be" | ||
| 23947 | " encrypted with Master Key encryption" | ||
| 23948 | " when online to KEYRING encryption is turned ON."); | ||
| 23949 | ✗ | return 1; | |
| 23950 | } | ||
| 23951 | } | ||
| 23952 | |||
| 23953 | /* If encryption is to be disabled. This will just make sure I/O doesn't | ||
| 23954 | write UNDO pages encrypted from now on. */ | ||
| 23955 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 44 times.
|
57 | if (target == false) { |
| 23956 | 13 | *static_cast<bool *>(save) = false; | |
| 23957 | 13 | return (0); | |
| 23958 | } | ||
| 23959 | |||
| 23960 | /* There would be at least 2 UNDO tablespaces */ | ||
| 23961 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
|
44 | ut_ad(undo::spaces->size() >= FSP_IMPLICIT_UNDO_TABLESPACES); |
| 23962 | |||
| 23963 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 39 times.
|
44 | if (!Encryption::check_keyring()) { |
| 23964 | 5 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_DA_UNDO_NO_KEYRING); | |
| 23965 | 5 | ib::error(ER_UNDO_NO_KEYRING); | |
| 23966 | 5 | return (0); | |
| 23967 | } | ||
| 23968 | |||
| 23969 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | if (srv_read_only_mode) { |
| 23970 | ✗ | ib::error(ER_IB_MSG_1051); | |
| 23971 | ✗ | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_IB_MSG_1051); | |
| 23972 | ✗ | return (0); | |
| 23973 | } | ||
| 23974 | |||
| 23975 | /* UNDO tablespace encryption to be mutually exclusive with any UNDO DDL */ | ||
| 23976 | 39 | mutex_enter(&undo::ddl_mutex); | |
| 23977 | |||
| 23978 | /* Enable encryption for UNDO tablespaces */ | ||
| 23979 | 39 | bool ret = srv_enable_undo_encryption(nullptr); | |
| 23980 | |||
| 23981 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 2 times.
|
39 | if (!ret) { |
| 23982 | /* At this point, all UNDO tablespaces have been encrypted. */ | ||
| 23983 | 37 | *static_cast<bool *>(save) = true; | |
| 23984 | } | ||
| 23985 | |||
| 23986 | 39 | mutex_exit(&undo::ddl_mutex); | |
| 23987 | 39 | return (0); | |
| 23988 | } | ||
| 23989 | |||
| 23990 | /** Validate the value of innodb_redo_log_encrypt global variable. This function | ||
| 23991 | is registered as a callback with MySQL. | ||
| 23992 | @param[in] thd thread handle | ||
| 23993 | @param[in] var pointer to system variable | ||
| 23994 | @param[in] save possibly updated variable value | ||
| 23995 | @param[in] value current variable value | ||
| 23996 | @return error code */ | ||
| 23997 | 110 | static int validate_innodb_redo_log_encrypt(THD *thd, SYS_VAR *var, void *save, | |
| 23998 | struct st_mysql_value *value) { | ||
| 23999 | /* Call the default check function first. */ | ||
| 24000 | 110 | auto error = check_func_bool(thd, var, save, value); | |
| 24001 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 107 times.
|
110 | if (error != 0) { |
| 24002 | 3 | return (error); | |
| 24003 | } | ||
| 24004 | 107 | bool target = *static_cast<bool *>(save); | |
| 24005 | |||
| 24006 | /* Set the default output to current value for all error cases. */ | ||
| 24007 | 107 | *static_cast<bool *>(save) = srv_redo_log_encrypt; | |
| 24008 | |||
| 24009 |
2/2✓ Branch 0 taken 57 times.
✓ Branch 1 taken 50 times.
|
107 | if (srv_redo_log_encrypt == target) { |
| 24010 | /* No change */ | ||
| 24011 | 57 | return (0); | |
| 24012 | } | ||
| 24013 | |||
| 24014 | /* If encryption is to be disabled. This will just make sure I/O doesn't | ||
| 24015 | write REDO encrypted from now on. */ | ||
| 24016 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 37 times.
|
50 | if (target == false) { |
| 24017 | 13 | *static_cast<bool *>(save) = false; | |
| 24018 | 13 | return (0); | |
| 24019 | } | ||
| 24020 | |||
| 24021 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | if (srv_read_only_mode) { |
| 24022 | ✗ | ib::error(ER_IB_MSG_LOG_FILES_CANNOT_ENCRYPT_IN_READ_ONLY); | |
| 24023 | ✗ | return (0); | |
| 24024 | } | ||
| 24025 | |||
| 24026 | /* Enable encryption for REDO tablespaces */ | ||
| 24027 | 37 | bool ret = srv_enable_redo_encryption(); | |
| 24028 | |||
| 24029 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 7 times.
|
37 | if (!ret) { |
| 24030 | /* At this point, REDO log is set to be encrypted. */ | ||
| 24031 | 30 | *static_cast<bool *>(save) = true; | |
| 24032 | } | ||
| 24033 | 37 | return (0); | |
| 24034 | } | ||
| 24035 | |||
| 24036 | 9 | static int innodb_sys_tablespace_encyption_validate( | |
| 24037 | THD *thd, SYS_VAR *var, void *save, struct st_mysql_value *value) { | ||
| 24038 | const char *innodb_sys_tablespace_encryption_input; | ||
| 24039 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 24040 | 9 | int len = sizeof(buff); | |
| 24041 | |||
| 24042 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | ut_a(save != nullptr); |
| 24043 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | ut_a(value != nullptr); |
| 24044 | |||
| 24045 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | innodb_sys_tablespace_encryption_input = value->val_str(value, buff, &len); |
| 24046 | |||
| 24047 | 9 | bool legit_value = false; | |
| 24048 | 9 | uint use = 0; | |
| 24049 | // The last item of sys_tablespace_encrypt_names is nullptr | ||
| 24050 | 9 | const size_t encrypt_names_cnt = | |
| 24051 | array_elements(sys_tablespace_encrypt_names) - 1; | ||
| 24052 | |||
| 24053 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5 times.
|
27 | for (; use < encrypt_names_cnt; use++) { |
| 24054 |
3/4✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 18 times.
|
22 | if (!innobase_strcasecmp(innodb_sys_tablespace_encryption_input, |
| 24055 | sys_tablespace_encrypt_names[use])) { | ||
| 24056 | 4 | legit_value = true; | |
| 24057 | 4 | break; | |
| 24058 | } | ||
| 24059 | } | ||
| 24060 | // It is possible that enum value was provided as the integer, not literal | ||
| 24061 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
|
9 | if (!legit_value) { |
| 24062 | 5 | int error = 0; | |
| 24063 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | use = (uint)my_strtoll10(innodb_sys_tablespace_encryption_input, nullptr, |
| 24064 | &error); | ||
| 24065 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
|
5 | if (!error && use < encrypt_names_cnt) { |
| 24066 | 2 | legit_value = true; | |
| 24067 | } | ||
| 24068 | } | ||
| 24069 | |||
| 24070 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
|
9 | if (!legit_value) return 1; |
| 24071 | |||
| 24072 | 6 | const auto change_to_sys_tablespace_encryption = | |
| 24073 | static_cast<srv_sys_tablespace_encrypt_enum>(use); | ||
| 24074 | |||
| 24075 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (change_to_sys_tablespace_encryption == SYS_TABLESPACE_ENCRYPT_OFF) { |
| 24076 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_ON) { |
| 24077 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24078 | "System tablespace Master Key encryption cannot be " | ||
| 24079 | "turned OFF dynamically. " | ||
| 24080 | "However you can still re-encrypt system tablespace " | ||
| 24081 | "with encryption threads " | ||
| 24082 | "and then instruct encryption threads to decrypt the " | ||
| 24083 | "system tablespace."); | ||
| 24084 | ✗ | return 1; | |
| 24085 | } | ||
| 24086 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING) { |
| 24087 | ✗ | push_warning_printf( | |
| 24088 | thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | ||
| 24089 | "RE_ENCRYPTING_TO_KEYRING can be only used when system tablespace " | ||
| 24090 | "was previously encrypted with Master Key encryption. To encrypt " | ||
| 24091 | "system tablespace with KEYRING encryption please use encryption " | ||
| 24092 | "threads."); | ||
| 24093 | ✗ | return 1; | |
| 24094 | } | ||
| 24095 | } | ||
| 24096 | |||
| 24097 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | if (change_to_sys_tablespace_encryption == SYS_TABLESPACE_ENCRYPT_ON) { |
| 24098 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_OFF) { |
| 24099 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | push_warning_printf( |
| 24100 | thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | ||
| 24101 | "System tablespace Master Key encryption can be turned ON only " | ||
| 24102 | "at bootstrap. You can still encrypt System tablespace encryption " | ||
| 24103 | "with " | ||
| 24104 | "KEYRING encryption."); | ||
| 24105 | 2 | return 1; | |
| 24106 | ✗ | } else if (srv_sys_tablespace_encrypt == | |
| 24107 | SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING) { | ||
| 24108 | // The system tablespace encryption was marked to be re-encrypted to | ||
| 24109 | // keyring. We allow it to be set back to ON in case encryption threads | ||
| 24110 | // were not yet activated and system tablespace remain encrypted with | ||
| 24111 | // Master Key. | ||
| 24112 | ✗ | if (Encryption::is_online_encryption_on()) { | |
| 24113 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24114 | "System tablespace cannot be marked as encrypted " | ||
| 24115 | "with Master Key encryption " | ||
| 24116 | "when Online to keyring encryption is turned ON or " | ||
| 24117 | "when system tablespace " | ||
| 24118 | "was already encrypted with KEYRING encryption."); | ||
| 24119 | ✗ | return 1; | |
| 24120 | } else { | ||
| 24121 | ✗ | fil_space_t *space = fil_space_acquire_silent(TRX_SYS_SPACE); | |
| 24122 | ✗ | ut_ad(space != nullptr); | |
| 24123 | ✗ | fil_space_crypt_t *crypt_data = space->crypt_data; | |
| 24124 | ✗ | fil_space_release(space); | |
| 24125 | |||
| 24126 | ✗ | if (crypt_data != nullptr) { | |
| 24127 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, | |
| 24128 | ER_WRONG_ARGUMENTS, | ||
| 24129 | "System tablespace cannot be marked as encrypted " | ||
| 24130 | "with Master Key encryption " | ||
| 24131 | "as it was already encrypted with KEYRING " | ||
| 24132 | "encryption and Master Key encryption " | ||
| 24133 | "is bootstrap only option."); | ||
| 24134 | ✗ | return 1; | |
| 24135 | } | ||
| 24136 | } | ||
| 24137 | } | ||
| 24138 | } | ||
| 24139 | |||
| 24140 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (change_to_sys_tablespace_encryption == |
| 24141 | 1 | SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING && | |
| 24142 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_OFF) { |
| 24143 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf( |
| 24144 | thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | ||
| 24145 | "System tablespace can only be marked to be re-encrypted with keyring " | ||
| 24146 | "in " | ||
| 24147 | "case it was previosly encrypted with Master Key encryption. " | ||
| 24148 | "You still can encrypt unencrypted system tablespace with encryption " | ||
| 24149 | "threads."); | ||
| 24150 | 1 | return 1; | |
| 24151 | } | ||
| 24152 | |||
| 24153 | 3 | *static_cast<ulong *>(save) = use; | |
| 24154 | |||
| 24155 | 3 | return 0; | |
| 24156 | } | ||
| 24157 | |||
| 24158 | /** Update the number of rollback segments per tablespace when the | ||
| 24159 | system variable innodb_rollback_segments is changed. | ||
| 24160 | This function is registered as a callback with MySQL. | ||
| 24161 | @param[in] save immediate result from check function */ | ||
| 24162 | 22 | static void innodb_rollback_segments_update(THD *, SYS_VAR *, void *, | |
| 24163 | const void *save) { | ||
| 24164 | 22 | ulong target = *static_cast<const ulong *>(save); | |
| 24165 | |||
| 24166 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 15 times.
|
22 | if (srv_rollback_segments == target) { |
| 24167 | 11 | return; | |
| 24168 | } | ||
| 24169 | |||
| 24170 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
|
15 | if (srv_read_only_mode) { |
| 24171 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | ib::warn(ER_IB_MSG_578) << "Cannot set innodb_rollback_segments to " |
| 24172 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | << target << " when in read-only mode"; |
| 24173 | 2 | return; | |
| 24174 | } | ||
| 24175 | |||
| 24176 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
|
13 | if (srv_force_recovery > 0) { |
| 24177 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | ib::warn(ER_IB_MSG_579) << "Cannot set innodb_rollback_segments to " |
| 24178 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | << target << " when in innodb_force_recovery > 0"; |
| 24179 | 2 | return; | |
| 24180 | } | ||
| 24181 | |||
| 24182 | /* Serialize this adjustment with all undo tablespace DDLs. */ | ||
| 24183 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | mutex_enter(&undo::ddl_mutex); |
| 24184 | |||
| 24185 |
2/4✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
|
11 | if (!trx_rseg_adjust_rollback_segments(target)) { |
| 24186 | ✗ | ib::warn(ER_IB_MSG_580) | |
| 24187 | ✗ | << "Failed to set innodb_rollback_segments to " << target; | |
| 24188 | ✗ | return; | |
| 24189 | } | ||
| 24190 | |||
| 24191 | 11 | srv_rollback_segments = target; | |
| 24192 | |||
| 24193 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | mutex_exit(&undo::ddl_mutex); |
| 24194 | } | ||
| 24195 | |||
| 24196 | /** Parse and enable InnoDB monitor counters during server startup. | ||
| 24197 | User can list the monitor counters/groups to be enable by specifying | ||
| 24198 | "loose-innodb_monitor_enable=monitor_name1;monitor_name2..." | ||
| 24199 | in server configuration file or at the command line. The string | ||
| 24200 | separate could be ";", "," or empty space. */ | ||
| 24201 | 2 | static void innodb_enable_monitor_at_startup( | |
| 24202 | char *str) /*!< in/out: monitor counter enable list */ | ||
| 24203 | { | ||
| 24204 | static const char *sep = " ;,"; | ||
| 24205 | char *last; | ||
| 24206 | |||
| 24207 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | ut_a(str); |
| 24208 | |||
| 24209 | /* Walk through the string, and separate each monitor counter | ||
| 24210 | and/or counter group name, and calling innodb_monitor_update() | ||
| 24211 | if successfully updated. Please note that the "str" would be | ||
| 24212 | changed by strtok_r() as it walks through it. */ | ||
| 24213 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | for (char *option = my_strtok_r(str, sep, &last); option; |
| 24214 | 2 | option = my_strtok_r(nullptr, sep, &last)) { | |
| 24215 | ulint ret; | ||
| 24216 | char *option_name; | ||
| 24217 | |||
| 24218 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ret = innodb_monitor_valid_byname(&option_name, option); |
| 24219 | |||
| 24220 | /* The name is validated if ret == 0 */ | ||
| 24221 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (!ret) { |
| 24222 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | innodb_monitor_update(nullptr, nullptr, &option, MONITOR_TURN_ON, false); |
| 24223 | } else { | ||
| 24224 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_INVALID_MONITOR_COUNTER_NAME, option); | |
| 24225 | } | ||
| 24226 | } | ||
| 24227 | 2 | } | |
| 24228 | |||
| 24229 | #if defined(UNIV_LINUX) && (defined(UNIV_DEBUG) || defined(UNIV_PERF_DEBUG)) | ||
| 24230 | |||
| 24231 | /** Update the innodb_sched_priority_purge variable and set the thread | ||
| 24232 | priorities accordingly. | ||
| 24233 | @param[in] thd thread handle | ||
| 24234 | @param[in] var pointer to system variable | ||
| 24235 | @param[out] var_ptr where the formal string goes | ||
| 24236 | @param[in] save immediate result from check function */ | ||
| 24237 | 8 | static void innodb_sched_priority_purge_update(THD *thd, SYS_VAR *var, | |
| 24238 | void *var_ptr, | ||
| 24239 | const void *save) { | ||
| 24240 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (srv_read_only_mode) return; |
| 24241 | |||
| 24242 | 8 | const ulint priority = *static_cast<const ulint *>(save); | |
| 24243 | |||
| 24244 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8 times.
|
40 | for (ulint i = 0; i < srv_n_purge_threads; i++) { |
| 24245 | const ulint actual_priority = | ||
| 24246 | 32 | os_thread_set_priority(srv_purge_tids[i], priority); | |
| 24247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (UNIV_UNLIKELY(actual_priority != priority)) { |
| 24248 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24249 | "Failed to set the purge thread priority to %lu, " | ||
| 24250 | "the current priority is %lu, aborting priority " | ||
| 24251 | "update", | ||
| 24252 | priority, actual_priority); | ||
| 24253 | ✗ | return; | |
| 24254 | } | ||
| 24255 | } | ||
| 24256 | |||
| 24257 | 8 | srv_sched_priority_purge = priority; | |
| 24258 | } | ||
| 24259 | |||
| 24260 | /** Update the innodb_sched_priority_io variable and set the thread priorities | ||
| 24261 | accordingly. | ||
| 24262 | @param[in] thd thread handle | ||
| 24263 | @param[in] var pointer to system variable | ||
| 24264 | @param[out] var_ptr where the formal string goes | ||
| 24265 | @param[in] save immediate result from check function */ | ||
| 24266 | 7 | static void innodb_sched_priority_io_update(THD *thd, SYS_VAR *var, | |
| 24267 | void *var_ptr, const void *save) { | ||
| 24268 | 7 | const ulint priority = *static_cast<const ulint *>(save); | |
| 24269 | |||
| 24270 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 7 times.
|
77 | for (ulint i = 0; i < srv_n_file_io_threads; i++) { |
| 24271 | const ulint actual_priority = | ||
| 24272 | 70 | os_thread_set_priority(srv_io_tids[i], priority); | |
| 24273 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
|
70 | if (UNIV_UNLIKELY(actual_priority != priority)) { |
| 24274 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24275 | "Failed to set the I/O thread priority to %lu, the " | ||
| 24276 | "current priority is %lu, aborting priority update", | ||
| 24277 | priority, actual_priority); | ||
| 24278 | ✗ | return; | |
| 24279 | } | ||
| 24280 | } | ||
| 24281 | 7 | srv_sched_priority_io = priority; | |
| 24282 | } | ||
| 24283 | |||
| 24284 | /** Update the innodb_sched_priority_master variable and set the thread | ||
| 24285 | priorities accordingly. | ||
| 24286 | @param[in] thd thread handle | ||
| 24287 | @param[in] var pointer to system variable | ||
| 24288 | @param[out] var_ptr where the formal string goes | ||
| 24289 | @param[in] save immediate result from check function */ | ||
| 24290 | 7 | static void innodb_sched_priority_master_update(THD *thd, SYS_VAR *var, | |
| 24291 | void *var_ptr, | ||
| 24292 | const void *save) { | ||
| 24293 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (srv_read_only_mode) return; |
| 24294 | |||
| 24295 | 7 | const ulint priority = *static_cast<const lint *>(save); | |
| 24296 | const ulint actual_priority = | ||
| 24297 | 7 | os_thread_set_priority(srv_master_tid, priority); | |
| 24298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (UNIV_UNLIKELY(actual_priority != priority)) { |
| 24299 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24300 | "Failed to set the master thread priority to %lu, the " | ||
| 24301 | "current priority is %lu", | ||
| 24302 | priority, actual_priority); | ||
| 24303 | } else { | ||
| 24304 | 7 | srv_sched_priority_master = priority; | |
| 24305 | } | ||
| 24306 | } | ||
| 24307 | |||
| 24308 | #endif /* defined(UNIV_LINUX) && (defined(UNIV_DEBUG) || \ | ||
| 24309 | defined(UNIV_PERF_DEBUG)) */ | ||
| 24310 | |||
| 24311 | /** Callback function for accessing the InnoDB variables from MySQL: | ||
| 24312 | SHOW VARIABLES. */ | ||
| 24313 | 142028 | static int show_innodb_vars(THD *, SHOW_VAR *var, char *) { | |
| 24314 | 142028 | innodb_export_status(); | |
| 24315 | 142027 | var->type = SHOW_ARRAY; | |
| 24316 | 142027 | var->value = (char *)&innodb_status_variables; | |
| 24317 | 142027 | var->scope = SHOW_SCOPE_GLOBAL; | |
| 24318 | |||
| 24319 | 142027 | return (0); | |
| 24320 | } | ||
| 24321 | |||
| 24322 | /** This function checks each index name for a table against reserved | ||
| 24323 | system default primary index name 'GEN_CLUST_INDEX'. If a name | ||
| 24324 | matches, this function pushes an warning message to the client, | ||
| 24325 | and returns true. | ||
| 24326 | @return true if the index name matches the reserved name */ | ||
| 24327 | 385055 | bool innobase_index_name_is_reserved( | |
| 24328 | THD *thd, /*!< in/out: MySQL connection */ | ||
| 24329 | const KEY *key_info, /*!< in: Indexes to be created */ | ||
| 24330 | ulint num_of_keys) /*!< in: Number of indexes to | ||
| 24331 | be created. */ | ||
| 24332 | { | ||
| 24333 | const KEY *key; | ||
| 24334 | uint key_num; /* index number */ | ||
| 24335 | |||
| 24336 |
2/2✓ Branch 0 taken 234265 times.
✓ Branch 1 taken 385052 times.
|
619317 | for (key_num = 0; key_num < num_of_keys; key_num++) { |
| 24337 | 234265 | key = &key_info[key_num]; | |
| 24338 | |||
| 24339 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 234262 times.
|
234265 | if (innobase_strcasecmp(key->name, innobase_index_reserve_name) == 0) { |
| 24340 | /* Push warning to mysql */ | ||
| 24341 | 3 | push_warning_printf(thd, Sql_condition::SL_WARNING, | |
| 24342 | ER_WRONG_NAME_FOR_INDEX, | ||
| 24343 | "Cannot Create Index with name" | ||
| 24344 | " '%s'. The name is reserved" | ||
| 24345 | " for the system default primary" | ||
| 24346 | " index.", | ||
| 24347 | innobase_index_reserve_name); | ||
| 24348 | |||
| 24349 | 3 | my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), innobase_index_reserve_name); | |
| 24350 | |||
| 24351 | 3 | return (true); | |
| 24352 | } | ||
| 24353 | } | ||
| 24354 | |||
| 24355 | 385052 | return (false); | |
| 24356 | } | ||
| 24357 | |||
| 24358 | /** Retrieve the FTS Relevance Ranking result for doc with doc_id | ||
| 24359 | of m_prebuilt->fts_doc_id | ||
| 24360 | @param[in,out] fts_hdl FTS handler | ||
| 24361 | @return the relevance ranking value */ | ||
| 24362 | 36908 | static float innobase_fts_retrieve_ranking(FT_INFO *fts_hdl) { | |
| 24363 | fts_result_t *result; | ||
| 24364 | row_prebuilt_t *ft_prebuilt [[maybe_unused]]; | ||
| 24365 | |||
| 24366 | 36908 | result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result; | |
| 24367 | |||
| 24368 | 36908 | ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt; | |
| 24369 | |||
| 24370 | 36908 | fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current); | |
| 24371 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36908 times.
|
36908 | assert(ft_prebuilt->fts_doc_id == ranking->doc_id); |
| 24372 | |||
| 24373 | 36908 | return (ranking->rank); | |
| 24374 | } | ||
| 24375 | |||
| 24376 | /** Free the memory for the FTS handler | ||
| 24377 | @param[in,out] fts_hdl FTS handler */ | ||
| 24378 | 2288 | static void innobase_fts_close_ranking(FT_INFO *fts_hdl) { | |
| 24379 | fts_result_t *result; | ||
| 24380 | |||
| 24381 | 2288 | result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result; | |
| 24382 | |||
| 24383 | 2288 | fts_query_free_result(result); | |
| 24384 | |||
| 24385 | 2288 | my_free((uchar *)fts_hdl); | |
| 24386 | 2288 | } | |
| 24387 | |||
| 24388 | /** Find and Retrieve the FTS Relevance Ranking result for doc with doc_id | ||
| 24389 | of m_prebuilt->fts_doc_id | ||
| 24390 | @param[in,out] fts_hdl FTS handler | ||
| 24391 | @return the relevance ranking value */ | ||
| 24392 | 5696 | static float innobase_fts_find_ranking(FT_INFO *fts_hdl, uchar *, uint) { | |
| 24393 | fts_result_t *result; | ||
| 24394 | row_prebuilt_t *ft_prebuilt; | ||
| 24395 | |||
| 24396 | 5696 | ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt; | |
| 24397 | 5696 | result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result; | |
| 24398 | |||
| 24399 | /* Retrieve the ranking value for doc_id with value of | ||
| 24400 | m_prebuilt->fts_doc_id */ | ||
| 24401 | 5696 | return (fts_retrieve_ranking(result, ft_prebuilt->fts_doc_id)); | |
| 24402 | } | ||
| 24403 | |||
| 24404 | #ifdef UNIV_DEBUG | ||
| 24405 | static bool innodb_background_drop_list_empty = true; | ||
| 24406 | static bool innodb_purge_run_now = true; | ||
| 24407 | static bool innodb_purge_stop_now = true; | ||
| 24408 | static bool innodb_log_checkpoint_now = true; | ||
| 24409 | static bool innodb_log_checkpoint_fuzzy_now = true; | ||
| 24410 | static bool innodb_log_flush_now = true; | ||
| 24411 | static bool innodb_buf_flush_list_now = true; | ||
| 24412 | |||
| 24413 | static uint innodb_merge_threshold_set_all_debug = | ||
| 24414 | DICT_INDEX_MERGE_THRESHOLD_DEFAULT; | ||
| 24415 | |||
| 24416 | /** Wait for the background drop list to become empty. */ | ||
| 24417 | 4 | static void wait_background_drop_list_empty(THD *, SYS_VAR *, void *, | |
| 24418 | const void *) { | ||
| 24419 | 4 | row_wait_for_background_drop_list_empty(); | |
| 24420 | 4 | } | |
| 24421 | |||
| 24422 | /** Set the purge state to RUN. If purge is disabled then it | ||
| 24423 | is a no-op. This function is registered as a callback with MySQL. | ||
| 24424 | @param[in] save immediate result from check function */ | ||
| 24425 | 387 | static void purge_run_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 24426 |
5/6✓ Branch 0 taken 384 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 384 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 384 times.
✓ Branch 5 taken 3 times.
|
387 | if (*(bool *)save && trx_purge_state() != PURGE_STATE_DISABLED) { |
| 24427 | 384 | trx_purge_run(); | |
| 24428 | } | ||
| 24429 | 387 | } | |
| 24430 | |||
| 24431 | /** Set the purge state to STOP. If purge is disabled then it | ||
| 24432 | is a no-op. This function is registered as a callback with MySQL. | ||
| 24433 | @param[in] save immediate result from check function */ | ||
| 24434 | 102 | static void purge_stop_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 24435 |
5/6✓ Branch 0 taken 97 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 97 times.
✓ Branch 5 taken 5 times.
|
102 | if (*(bool *)save && trx_purge_state() != PURGE_STATE_DISABLED) { |
| 24436 | 97 | trx_purge_stop(); | |
| 24437 | } | ||
| 24438 | 102 | } | |
| 24439 | |||
| 24440 | /** Force InnoDB to flush redo log up to current_lsn. | ||
| 24441 | This function is registered as a callback with MySQL. | ||
| 24442 | @param[in] save immediate result from check function */ | ||
| 24443 | 8 | static void log_flush_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 24444 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | if (!*(bool *)save) { |
| 24445 | 6 | return; | |
| 24446 | } | ||
| 24447 | |||
| 24448 | 2 | log_buffer_flush_to_disk(true); | |
| 24449 | } | ||
| 24450 | |||
| 24451 | /** Force InnoDB to do sharp checkpoint. This forces a flush of all | ||
| 24452 | dirty pages. | ||
| 24453 | @param[in] save immediate result from check function */ | ||
| 24454 | 31 | static void checkpoint_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 24455 |
3/4✓ Branch 0 taken 24 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
31 | if (*(bool *)save && !srv_checkpoint_disabled) { |
| 24456 | /* Note that it's defined only when UNIV_DEBUG is defined. | ||
| 24457 | It seems to be very risky feature. Fortunately it is used | ||
| 24458 | only inside mtr tests. */ | ||
| 24459 | |||
| 24460 |
2/2✓ Branch 0 taken 73 times.
✓ Branch 1 taken 24 times.
|
97 | while (log_make_latest_checkpoint(*log_sys)) { |
| 24461 | /* Creating checkpoint could itself result in | ||
| 24462 | new log records. Hence we repeat until: | ||
| 24463 | last_checkpoint_lsn = log_get_lsn(). */ | ||
| 24464 | } | ||
| 24465 | |||
| 24466 | 48 | dberr_t err = fil_write_flushed_lsn(log_sys->last_checkpoint_lsn.load()); | |
| 24467 | |||
| 24468 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | ut_a(err == DB_SUCCESS); |
| 24469 | } | ||
| 24470 | 31 | } | |
| 24471 | |||
| 24472 | /** Force InnoDB to do fuzzy checkpoint. Fuzzy checkpoint does not | ||
| 24473 | force InnoDB to flush dirty pages. It only forces to write the new | ||
| 24474 | checkpoint_lsn to the header of the log file containing that LSN. | ||
| 24475 | This LSN is where the recovery starts. You can read more about the | ||
| 24476 | fuzzy checkpoints in the internet. | ||
| 24477 | @param[in] save immediate result from check function */ | ||
| 24478 | 8 | static void checkpoint_fuzzy_now_set(THD *, SYS_VAR *, void *, | |
| 24479 | const void *save) { | ||
| 24480 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
8 | if (*(bool *)save && !srv_checkpoint_disabled) { |
| 24481 | /* Note that it's defined only when UNIV_DEBUG is defined. | ||
| 24482 | It seems to be very risky feature. Fortunately it is used | ||
| 24483 | only inside mtr tests. */ | ||
| 24484 | |||
| 24485 | 2 | log_request_checkpoint(*log_sys, true); | |
| 24486 | } | ||
| 24487 | 8 | } | |
| 24488 | |||
| 24489 | /** Updates srv_checkpoint_disabled - allowing or disallowing checkpoints. | ||
| 24490 | This is called when user invokes SET GLOBAL innodb_checkpoints_disabled=0/1. | ||
| 24491 | After checkpoints are disabled, there will be no write of a checkpoint, | ||
| 24492 | until checkpoints are re-enabled (log_sys->checkpointer_mutex protects that) | ||
| 24493 | @param[in] save immediate result from check function */ | ||
| 24494 | 94 | static void checkpoint_disabled_update(THD *, SYS_VAR *, void *, | |
| 24495 | const void *save) { | ||
| 24496 | /* We need to acquire the checkpointer_mutex, to ensure that | ||
| 24497 | after we have finished this function, there will be no new | ||
| 24498 | checkpoint written (e.g. in case there is currently curring | ||
| 24499 | checkpoint). When checkpoint is being written, the same mutex | ||
| 24500 | is acquired, current value of srv_checkpoint_disabled is checked, | ||
| 24501 | and if checkpoints are disabled, we cancel writing the checkpoint. */ | ||
| 24502 | |||
| 24503 | 94 | log_t &log = *log_sys; | |
| 24504 | |||
| 24505 | 94 | log_checkpointer_mutex_enter(log); | |
| 24506 | 94 | log_limits_mutex_enter(log); | |
| 24507 | |||
| 24508 | 94 | srv_checkpoint_disabled = *static_cast<const bool *>(save); | |
| 24509 | |||
| 24510 | 94 | log_limits_mutex_exit(log); | |
| 24511 | 94 | log_checkpointer_mutex_exit(log); | |
| 24512 | 94 | } | |
| 24513 | |||
| 24514 | /** Force a dirty pages flush now. | ||
| 24515 | @param[in] save immediate result from check function */ | ||
| 24516 | 200 | static void buf_flush_list_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 24517 |
2/2✓ Branch 0 taken 195 times.
✓ Branch 1 taken 5 times.
|
200 | if (*(bool *)save) { |
| 24518 | 195 | buf_flush_sync_all_buf_pools(); | |
| 24519 | } | ||
| 24520 | 200 | } | |
| 24521 | |||
| 24522 | /** Override current MERGE_THRESHOLD setting for all indexes at dictionary | ||
| 24523 | now. | ||
| 24524 | @param[in] save immediate result from check function */ | ||
| 24525 | 7 | static void innodb_merge_threshold_set_all_debug_update(THD *, SYS_VAR *, | |
| 24526 | void *, | ||
| 24527 | const void *save) { | ||
| 24528 | 7 | innodb_merge_threshold_set_all_debug = (*static_cast<const uint *>(save)); | |
| 24529 | 7 | dict_set_merge_threshold_all_debug(innodb_merge_threshold_set_all_debug); | |
| 24530 | 7 | } | |
| 24531 | |||
| 24532 | #endif /* UNIV_DEBUG */ | ||
| 24533 | |||
| 24534 | /** Find and Retrieve the FTS doc_id for the current result row | ||
| 24535 | @param[in,out] fts_hdl FTS handler | ||
| 24536 | @return the document ID */ | ||
| 24537 | ✗ | static ulonglong innobase_fts_retrieve_docid(FT_INFO_EXT *fts_hdl) { | |
| 24538 | fts_result_t *result; | ||
| 24539 | row_prebuilt_t *ft_prebuilt; | ||
| 24540 | |||
| 24541 | ✗ | ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt; | |
| 24542 | ✗ | result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result; | |
| 24543 | |||
| 24544 | ✗ | if (ft_prebuilt->read_just_key) { | |
| 24545 | ✗ | fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current); | |
| 24546 | |||
| 24547 | ✗ | return (ranking->doc_id); | |
| 24548 | } | ||
| 24549 | |||
| 24550 | ✗ | return (ft_prebuilt->fts_doc_id); | |
| 24551 | } | ||
| 24552 | |||
| 24553 | /* These variables are never read by InnoDB or changed. They are a kind of | ||
| 24554 | dummies that are needed by the MySQL infrastructure to call | ||
| 24555 | buffer_pool_dump_now(), buffer_pool_load_now() and buffer_pool_load_abort() | ||
| 24556 | by the user by doing: | ||
| 24557 | SET GLOBAL innodb_buffer_pool_dump_now=ON; | ||
| 24558 | SET GLOBAL innodb_buffer_pool_load_now=ON; | ||
| 24559 | SET GLOBAL innodb_buffer_pool_load_abort=ON; | ||
| 24560 | Their values are read by MySQL and displayed to the user when the variables | ||
| 24561 | are queried, e.g.: | ||
| 24562 | SELECT @@innodb_buffer_pool_dump_now; | ||
| 24563 | SELECT @@innodb_buffer_pool_load_now; | ||
| 24564 | SELECT @@innodb_buffer_pool_load_abort; */ | ||
| 24565 | static bool innodb_buffer_pool_dump_now = false; | ||
| 24566 | static bool innodb_buffer_pool_load_now = false; | ||
| 24567 | static bool innodb_buffer_pool_load_abort = false; | ||
| 24568 | |||
| 24569 | /** Trigger a dump of the buffer pool if innodb_buffer_pool_dump_now is set | ||
| 24570 | to ON. This function is registered as a callback with MySQL. | ||
| 24571 | @param[in] save immediate result from check function */ | ||
| 24572 | 10 | static void buffer_pool_dump_now(THD *, SYS_VAR *, void *, const void *save) { | |
| 24573 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
10 | if (*(bool *)save && !srv_read_only_mode) { |
| 24574 | 7 | buf_dump_start(); | |
| 24575 | } | ||
| 24576 | 10 | } | |
| 24577 | |||
| 24578 | /** Trigger a load of the buffer pool if innodb_buffer_pool_load_now is set | ||
| 24579 | to ON. This function is registered as a callback with MySQL. | ||
| 24580 | @param[in] save immediate result from check function */ | ||
| 24581 | 9 | static void buffer_pool_load_now(THD *, SYS_VAR *, void *, const void *save) { | |
| 24582 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
|
9 | if (*(bool *)save) { |
| 24583 | 6 | buf_load_start(); | |
| 24584 | } | ||
| 24585 | 9 | } | |
| 24586 | |||
| 24587 | /** Abort a load of the buffer pool if innodb_buffer_pool_load_abort | ||
| 24588 | is set to ON. This function is registered as a callback with MySQL. | ||
| 24589 | @param[in] save immediate result from check function */ | ||
| 24590 | 4 | static void buffer_pool_load_abort(THD *, SYS_VAR *, void *, const void *save) { | |
| 24591 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (*(bool *)save) { |
| 24592 | 1 | buf_load_abort(); | |
| 24593 | } | ||
| 24594 | 4 | } | |
| 24595 | |||
| 24596 | /** Update the system variable innodb_log_write_ahead_size using the "saved" | ||
| 24597 | value. This function is registered as a callback with MySQL. | ||
| 24598 | @param[in] thd thread handle | ||
| 24599 | @param[in] save immediate result from check function */ | ||
| 24600 | 163 | static void innodb_log_write_ahead_size_update(THD *thd, SYS_VAR *, void *, | |
| 24601 | const void *save) { | ||
| 24602 | 163 | ulong val = INNODB_LOG_WRITE_AHEAD_SIZE_MIN; | |
| 24603 | 163 | ulong in_val = *static_cast<const ulong *>(save); | |
| 24604 | |||
| 24605 |
2/2✓ Branch 0 taken 424 times.
✓ Branch 1 taken 163 times.
|
587 | while (val < in_val) { |
| 24606 | 424 | val = val * 2; | |
| 24607 | } | ||
| 24608 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163 times.
|
163 | if (val > INNODB_LOG_WRITE_AHEAD_SIZE_MAX) { |
| 24609 | ✗ | val = INNODB_LOG_WRITE_AHEAD_SIZE_MAX; | |
| 24610 | } | ||
| 24611 | |||
| 24612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163 times.
|
163 | if (val > UNIV_PAGE_SIZE) { |
| 24613 | ✗ | val = UNIV_PAGE_SIZE; | |
| 24614 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24615 | "innodb_log_write_ahead_size cannot" | ||
| 24616 | " be set higher than innodb_page_size."); | ||
| 24617 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 162 times.
|
163 | } else if (val != in_val) { |
| 24618 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24619 | "innodb_log_write_ahead_size should be" | ||
| 24620 | " set to power of 2, in range [%lu,%lu]", | ||
| 24621 | INNODB_LOG_WRITE_AHEAD_SIZE_MIN, | ||
| 24622 | INNODB_LOG_WRITE_AHEAD_SIZE_MAX); | ||
| 24623 | } | ||
| 24624 | |||
| 24625 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 162 times.
|
163 | if (val != in_val) { |
| 24626 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24627 | "Setting innodb_log_write_ahead_size" | ||
| 24628 | " to %lu", | ||
| 24629 | val); | ||
| 24630 | } | ||
| 24631 | |||
| 24632 | 163 | log_write_ahead_resize(*log_sys, val); | |
| 24633 | 163 | } | |
| 24634 | |||
| 24635 | /** Update the system variable innodb_log_buffer_size using the "saved" | ||
| 24636 | value. This function is registered as a callback with MySQL. | ||
| 24637 | @param[in] save immediate result from check function */ | ||
| 24638 | 165 | static void innodb_log_buffer_size_update(THD *, SYS_VAR *, void *, | |
| 24639 | const void *save) { | ||
| 24640 | 165 | const ulong val = *static_cast<const ulong *>(save); | |
| 24641 | |||
| 24642 |
3/6✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✗ Branch 5 not taken.
|
165 | ib::info(ER_IB_MSG_1255) << "Setting innodb_log_buffer_size to " << val; |
| 24643 | |||
| 24644 |
2/4✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 165 times.
|
165 | if (!log_buffer_resize(*log_sys, val)) { |
| 24645 | /* This could happen if we tried to decrease size of the | ||
| 24646 | log buffer but we had more data in the log buffer than | ||
| 24647 | the new size. We could have asked for writing the data to | ||
| 24648 | disk, after x-locking the log buffer, but this could lead | ||
| 24649 | to deadlock if there was no space in log files and checkpoint | ||
| 24650 | was required (because checkpoint writes new redo records | ||
| 24651 | when persisting dd table buffer). That's why we don't ask | ||
| 24652 | for writing to disk. */ | ||
| 24653 | |||
| 24654 | ✗ | ib::error(ER_IB_MSG_1256) << "Failed to change size of the log buffer." | |
| 24655 | ✗ | " Try flushing the log buffer first."; | |
| 24656 | } | ||
| 24657 | 165 | } | |
| 24658 | |||
| 24659 | /** Update the innodb_log_writer_threads parameter. | ||
| 24660 | @param[out] var_ptr current value | ||
| 24661 | @param[in] save immediate result from check function */ | ||
| 24662 | 6 | static void innodb_log_writer_threads_update(THD *, SYS_VAR *, void *var_ptr, | |
| 24663 | const void *save) { | ||
| 24664 | 6 | *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save); | |
| 24665 | |||
| 24666 | /* pause/resume the log writer threads based on innodb_log_writer_threads | ||
| 24667 | value. */ | ||
| 24668 | 6 | log_control_writer_threads(*log_sys); | |
| 24669 | 6 | } | |
| 24670 | |||
| 24671 | /** Update the system variable innodb_redo_log_capacity using the "saved" | ||
| 24672 | value. This function is registered as a callback with MySQL. | ||
| 24673 | @param[in] thd thread handle | ||
| 24674 | @param[in] save immediate result from check function */ | ||
| 24675 | 10 | static void innodb_redo_log_capacity_update(THD *thd, SYS_VAR *, void *, | |
| 24676 | const void *save) { | ||
| 24677 | 10 | const auto new_value = *static_cast<const ulonglong *>(save); | |
| 24678 | |||
| 24679 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | ut_a(LOG_CAPACITY_MIN <= new_value); |
| 24680 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | ut_a(new_value <= LOG_CAPACITY_MAX); |
| 24681 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | ut_a(new_value % MB == 0); |
| 24682 | |||
| 24683 | 10 | srv_redo_log_capacity = new_value; | |
| 24684 | |||
| 24685 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
|
10 | if (new_value == srv_redo_log_capacity_used) { |
| 24686 | 4 | return; | |
| 24687 | } | ||
| 24688 | |||
| 24689 | 6 | srv_redo_log_capacity_used = new_value; | |
| 24690 | |||
| 24691 | 6 | ib::info(ER_IB_MSG_LOG_FILES_CAPACITY_CHANGED, | |
| 24692 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | srv_redo_log_capacity_used / MB); |
| 24693 | |||
| 24694 | 6 | log_files_resize_requested(*log_sys); | |
| 24695 | |||
| 24696 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!log_sys->concurrency_margin_is_safe.load()) { |
| 24697 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24698 | "Current innodb_redo_log_capacity" | ||
| 24699 | " is too small for safety of redo log files." | ||
| 24700 | " Consider increasing it or decreasing" | ||
| 24701 | " innodb_thread_concurrency."); | ||
| 24702 | } | ||
| 24703 | } | ||
| 24704 | |||
| 24705 | /** Update the system variable innodb_thread_concurrency using the "saved" | ||
| 24706 | value. This function is registered as a callback with MySQL. | ||
| 24707 | @param[in] thd thread handle | ||
| 24708 | @param[in] save immediate result from check function */ | ||
| 24709 | 36 | static void innodb_thread_concurrency_update(THD *thd, SYS_VAR *, void *, | |
| 24710 | const void *save) { | ||
| 24711 | 36 | srv_thread_concurrency = *static_cast<const ulong *>(save); | |
| 24712 | |||
| 24713 | 36 | ib::info(ER_IB_MSG_THREAD_CONCURRENCY_CHANGED, srv_thread_concurrency); | |
| 24714 | |||
| 24715 | 36 | log_files_thread_concurrency_updated(*log_sys); | |
| 24716 | |||
| 24717 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 33 times.
|
36 | if (!log_sys->concurrency_margin_is_safe.load()) { |
| 24718 | 3 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24719 | "Current innodb_thread_concurrency" | ||
| 24720 | " is too big for safety of redo log files." | ||
| 24721 | " Consider decreasing it or increasing" | ||
| 24722 | " innodb_redo_log_capacity."); | ||
| 24723 | } | ||
| 24724 | 36 | } | |
| 24725 | |||
| 24726 | /** Empty free list algorithm. This function is registered as a callback with | ||
| 24727 | MySQL. | ||
| 24728 | @param[in] thd thread handle | ||
| 24729 | @param[in] var pointer to system variable | ||
| 24730 | @param[out] save immediate result for update function | ||
| 24731 | @param[in] value incoming string | ||
| 24732 | @return 0 for valid algorithm */ | ||
| 24733 | 13 | static int innodb_srv_empty_free_list_algorithm_validate( | |
| 24734 | THD *thd, SYS_VAR *var, void *save, struct st_mysql_value *value) { | ||
| 24735 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 24736 | 13 | int len = sizeof(buff); | |
| 24737 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | const char *const algorithm_name = value->val_str(value, buff, &len); |
| 24738 | |||
| 24739 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!algorithm_name) return (1); |
| 24740 | |||
| 24741 | ulint algo; | ||
| 24742 | 22 | for (algo = 0; | |
| 24743 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
|
22 | algo < array_elements(innodb_empty_free_list_algorithm_names) - 1; |
| 24744 | algo++) { | ||
| 24745 |
3/4✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 9 times.
|
20 | if (!innobase_strcasecmp(algorithm_name, |
| 24746 | innodb_empty_free_list_algorithm_names[algo])) | ||
| 24747 | 11 | break; | |
| 24748 | } | ||
| 24749 | |||
| 24750 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
|
13 | if (algo == array_elements(innodb_empty_free_list_algorithm_names) - 1) |
| 24751 | 2 | return (1); | |
| 24752 | |||
| 24753 | 11 | const auto algorithm = static_cast<srv_empty_free_list_t>(algo); | |
| 24754 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
|
11 | if (!innodb_empty_free_list_algorithm_allowed(algorithm)) { |
| 24755 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | sql_print_warning( |
| 24756 | "InnoDB: innodb_empty_free_list_algorithm = 'backoff' " | ||
| 24757 | "requires at least 20MB buffer pool instances.\n"); | ||
| 24758 | 2 | return (1); | |
| 24759 | } | ||
| 24760 | |||
| 24761 | 9 | *reinterpret_cast<ulong *>(save) = static_cast<ulong>(algorithm); | |
| 24762 | 9 | return (0); | |
| 24763 | } | ||
| 24764 | |||
| 24765 | 10 | static int innodb_encryption_threads_validate( | |
| 24766 | /*=================================*/ | ||
| 24767 | THD *thd, /*!< in: thread handle */ | ||
| 24768 | SYS_VAR *var, /*!< in: pointer to system | ||
| 24769 | variable */ | ||
| 24770 | void *save, /*!< out: immediate result | ||
| 24771 | for update function */ | ||
| 24772 | struct st_mysql_value *value) /*!< in: incoming string */ | ||
| 24773 | { | ||
| 24774 | long long intbuf; | ||
| 24775 | |||
| 24776 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | DBUG_TRACE; |
| 24777 | |||
| 24778 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | if (value->val_int(value, &intbuf)) { |
| 24779 | /* The value is NULL. That is invalid. */ | ||
| 24780 | ✗ | return 1; | |
| 24781 | } | ||
| 24782 | |||
| 24783 | 10 | bool is_val_fixed = false; | |
| 24784 | 10 | long long requested_threads = intbuf; | |
| 24785 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
|
10 | if (intbuf < 0) { |
| 24786 | 2 | requested_threads = 0; | |
| 24787 | 2 | is_val_fixed = true; | |
| 24788 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
|
8 | } else if (intbuf > MAX_ENCRYPTION_THREADS) { |
| 24789 | 2 | requested_threads = MAX_ENCRYPTION_THREADS; | |
| 24790 | 2 | is_val_fixed = true; | |
| 24791 | } | ||
| 24792 | |||
| 24793 |
3/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
|
10 | if (throw_bounds_warning(thd, "innodb_encryption_threads", is_val_fixed, |
| 24794 | intbuf)) { | ||
| 24795 | 2 | return 1; | |
| 24796 | } | ||
| 24797 | |||
| 24798 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
|
8 | if (srv_n_fil_crypt_threads_requested == 0 && requested_threads > 0) { |
| 24799 | // We are starting encryption threads, we must lock | ||
| 24800 | // the keyring plugins | ||
| 24801 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | uint number_of_keyrings_locked = lock_keyrings(NULL); |
| 24802 | |||
| 24803 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (number_of_keyrings_locked == 0) { |
| 24804 | ✗ | my_printf_error(ER_WRONG_ARGUMENTS, | |
| 24805 | "InnoDB: cannot enable encryption threads, " | ||
| 24806 | "keyring plugin is not available", | ||
| 24807 | MYF(0)); | ||
| 24808 | ✗ | return 1; | |
| 24809 | } | ||
| 24810 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (Encryption::is_keyring_alive() == false) { |
| 24811 | ✗ | my_printf_error( | |
| 24812 | ER_WRONG_ARGUMENTS, | ||
| 24813 | "InnoDB: keyring plugin is installed but it seems it was not " | ||
| 24814 | "properly initialized. Cannot enable encryption threads.", | ||
| 24815 | MYF(0)); | ||
| 24816 | ✗ | unlock_keyrings(NULL); | |
| 24817 | ✗ | return 1; | |
| 24818 | } | ||
| 24819 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
|
8 | } else if (requested_threads == 0 && srv_n_fil_crypt_threads_requested > |
| 24820 | 0) { // We are disabling encryption | ||
| 24821 | // threads, unlock the keyrings | ||
| 24822 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | unlock_keyrings(NULL); |
| 24823 | } | ||
| 24824 | |||
| 24825 | 8 | *reinterpret_cast<ulong *>(save) = static_cast<ulong>(requested_threads); | |
| 24826 | |||
| 24827 | 8 | return 0; | |
| 24828 | 10 | } | |
| 24829 | |||
| 24830 | /****************************************************************** | ||
| 24831 | Update the system variable innodb_encryption_threads */ | ||
| 24832 | 8 | static void innodb_encryption_threads_update( | |
| 24833 | /*=============================*/ | ||
| 24834 | THD *thd, /*!< in: thread handle */ | ||
| 24835 | SYS_VAR *var, /*!< in: pointer to | ||
| 24836 | system variable */ | ||
| 24837 | void *var_ptr, /*!< out: where the | ||
| 24838 | formal string goes */ | ||
| 24839 | const void *save) /*!< in: immediate result | ||
| 24840 | from check function */ | ||
| 24841 | { | ||
| 24842 | 8 | mysql_mutex_unlock(&LOCK_global_system_variables); | |
| 24843 | 8 | fil_crypt_set_thread_cnt(*static_cast<const uint *>(save)); | |
| 24844 | 8 | mysql_mutex_lock(&LOCK_global_system_variables); | |
| 24845 | 8 | } | |
| 24846 | |||
| 24847 | /****************************************************************** | ||
| 24848 | Update the system variable innodb_encryption_rotate_key_age */ | ||
| 24849 | 3 | static void innodb_encryption_rotate_key_age_update( | |
| 24850 | /*====================================*/ | ||
| 24851 | THD *thd, /*!< in: thread handle */ | ||
| 24852 | SYS_VAR *var, /*!< in: pointer to | ||
| 24853 | system variable */ | ||
| 24854 | void *var_ptr, /*!< out: where the | ||
| 24855 | formal string goes */ | ||
| 24856 | const void *save) /*!< in: immediate result | ||
| 24857 | from check function */ | ||
| 24858 | { | ||
| 24859 | 3 | fil_crypt_set_rotate_key_age(*static_cast<const uint *>(save)); | |
| 24860 | 3 | } | |
| 24861 | |||
| 24862 | /****************************************************************** | ||
| 24863 | Update the system variable innodb_encryption_rotation_iops */ | ||
| 24864 | 3 | static void innodb_encryption_rotation_iops_update( | |
| 24865 | /*===================================*/ | ||
| 24866 | THD *thd, /*!< in: thread handle */ | ||
| 24867 | SYS_VAR *var, /*!< in: pointer to | ||
| 24868 | system variable */ | ||
| 24869 | void *var_ptr, /*!< out: where the | ||
| 24870 | formal string goes */ | ||
| 24871 | const void *save) /*!< in: immediate result | ||
| 24872 | from check function */ | ||
| 24873 | { | ||
| 24874 | 3 | fil_crypt_set_rotation_iops(*static_cast<const uint *>(save)); | |
| 24875 | 3 | } | |
| 24876 | |||
| 24877 | /** Update the innodb_log_checksums parameter. | ||
| 24878 | @param[out] var_ptr current value | ||
| 24879 | @param[in] save immediate result from check function */ | ||
| 24880 | 7 | static void innodb_log_checksums_update(THD *, SYS_VAR *, void *var_ptr, | |
| 24881 | const void *save) { | ||
| 24882 | 7 | bool check = *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save); | |
| 24883 | |||
| 24884 | /* Make sure we are the only log user */ | ||
| 24885 | 7 | innodb_log_checksums_func_update(check); | |
| 24886 | 7 | } | |
| 24887 | |||
| 24888 | /** Enable or disable encryption of temporary tablespace | ||
| 24889 | @param[in] thd thread handle | ||
| 24890 | @param[in] var system variable | ||
| 24891 | @param[out] var_ptr current value | ||
| 24892 | @param[in] save immediate result from check function */ | ||
| 24893 | 15 | static void innodb_temp_tablespace_encryption_update(THD *thd, SYS_VAR *var, | |
| 24894 | void *var_ptr, | ||
| 24895 | const void *save) { | ||
| 24896 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
|
15 | if (srv_read_only_mode) { |
| 24897 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24898 | " Temporary tablespace cannot be" | ||
| 24899 | " encrypted in innodb_read_only mode"); | ||
| 24900 | 1 | return; | |
| 24901 | } | ||
| 24902 | |||
| 24903 | 14 | bool check = *static_cast<const bool *>(save); | |
| 24904 | |||
| 24905 | 14 | dberr_t err = srv_temp_encryption_update(check); | |
| 24906 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
|
14 | if (err != DB_SUCCESS) { |
| 24907 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 24908 | " Temporary tablespace couldn't be" | ||
| 24909 | " encrypted. Check if keyring plugin" | ||
| 24910 | " is loaded."); | ||
| 24911 | } else { | ||
| 24912 | 12 | *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save); | |
| 24913 | } | ||
| 24914 | } | ||
| 24915 | |||
| 24916 | static SHOW_VAR innodb_status_variables_export[] = { | ||
| 24917 | {"Innodb", (char *)&show_innodb_vars, SHOW_FUNC, SHOW_SCOPE_GLOBAL}, | ||
| 24918 | {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}}; | ||
| 24919 | |||
| 24920 | static struct st_mysql_storage_engine innobase_storage_engine = { | ||
| 24921 | MYSQL_HANDLERTON_INTERFACE_VERSION}; | ||
| 24922 | |||
| 24923 | #ifdef WITH_WSREP | ||
| 24924 | ✗ | void wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) { | |
| 24925 | ✗ | WSREP_ERROR( | |
| 24926 | "Trx %lld tries to abort slave trx %lld. This could be " | ||
| 24927 | "caused by:\n\t" | ||
| 24928 | "1) unsupported configuration options combination, please check " | ||
| 24929 | "documentation.\n\t" | ||
| 24930 | "2) a bug in the code.\n\t" | ||
| 24931 | "3) a database corruption.\n Node consistency compromized, " | ||
| 24932 | "need to abort. Restart the node to resync with cluster.", | ||
| 24933 | (long long)bf_seqno, (long long)victim_seqno); | ||
| 24934 | ✗ | abort(); | |
| 24935 | } | ||
| 24936 | |||
| 24937 | 484 | int wsrep_innobase_kill_one_trx(void *const bf_thd_ptr, | |
| 24938 | const trx_t *const bf_trx, trx_t *victim_trx, | ||
| 24939 | bool signal) { | ||
| 24940 | // This is there in upstream codership 5.6 but causes | ||
| 24941 | // crashes, hence disabled | ||
| 24942 | // ut_ad(trx_mutex_own(victim_trx)); | ||
| 24943 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
|
484 | ut_ad(bf_thd_ptr); |
| 24944 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
|
484 | ut_ad(victim_trx); |
| 24945 | |||
| 24946 |
1/2✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
|
484 | DBUG_TRACE; |
| 24947 | 484 | THD *bf_thd = bf_thd_ptr ? (THD *)bf_thd_ptr : NULL; | |
| 24948 | 484 | THD *thd = (THD *)victim_trx->mysql_thd; | |
| 24949 |
2/4✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 484 times.
✗ Branch 3 not taken.
|
484 | int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; |
| 24950 | |||
| 24951 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
|
484 | if (!thd) { |
| 24952 | ✗ | DBUG_PRINT("wsrep", ("no thd for conflicting lock")); | |
| 24953 | ✗ | WSREP_WARN("no THD for victim trx: %llu", (long long)victim_trx->id); | |
| 24954 | ✗ | return 1; | |
| 24955 | } | ||
| 24956 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
|
484 | if (!bf_thd) { |
| 24957 | ✗ | DBUG_PRINT("wsrep", ("no BF thd for conflicting lock")); | |
| 24958 | ✗ | WSREP_WARN("no THD for BF trx: %llu", (bf_trx) ? (long long)bf_trx->id : 0); | |
| 24959 | ✗ | return 1; | |
| 24960 | } | ||
| 24961 | |||
| 24962 |
57/120✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 482 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 2 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 2 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 2 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 2 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 2 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 2 times.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✓ Branch 45 taken 2 times.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 2 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 2 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 2 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 2 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 2 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 2 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 2 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 2 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 2 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 2 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 2 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 2 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 2 times.
✗ Branch 73 not taken.
✓ Branch 74 taken 2 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 2 times.
✗ Branch 77 not taken.
✓ Branch 78 taken 2 times.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✓ Branch 81 taken 2 times.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✓ Branch 84 taken 2 times.
✗ Branch 85 not taken.
✓ Branch 86 taken 2 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 2 times.
✗ Branch 89 not taken.
✓ Branch 90 taken 2 times.
✗ Branch 91 not taken.
✓ Branch 92 taken 2 times.
✗ Branch 93 not taken.
✓ Branch 94 taken 2 times.
✗ Branch 95 not taken.
✓ Branch 96 taken 2 times.
✗ Branch 97 not taken.
✓ Branch 98 taken 2 times.
✗ Branch 99 not taken.
✓ Branch 100 taken 2 times.
✗ Branch 101 not taken.
✓ Branch 102 taken 2 times.
✗ Branch 103 not taken.
✓ Branch 104 taken 2 times.
✗ Branch 105 not taken.
✓ Branch 106 taken 2 times.
✗ Branch 107 not taken.
✓ Branch 108 taken 2 times.
✗ Branch 109 not taken.
✓ Branch 110 taken 2 times.
✗ Branch 111 not taken.
✓ Branch 112 taken 2 times.
✗ Branch 113 not taken.
✓ Branch 114 taken 2 times.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✓ Branch 117 taken 2 times.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
|
484 | WSREP_LOG_CONFLICT(bf_thd, thd, true); |
| 24963 |
1/2✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
|
484 | wsrep_thd_LOCK(thd); |
| 24964 | |||
| 24965 |
1/28✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
|
484 | WSREP_DEBUG( |
| 24966 | "BF thread %u (with write-set: %lld)" | ||
| 24967 | " aborting Victim thread %u with transaction (%llu)", | ||
| 24968 | wsrep_thd_thread_id(bf_thd), (long long)bf_seqno, | ||
| 24969 | wsrep_thd_thread_id(thd), (long long)victim_trx->id); | ||
| 24970 | |||
| 24971 |
1/32✗ Branch 0 not taken.
✓ Branch 1 taken 484 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
|
484 | WSREP_DEBUG("Aborting query: %s", |
| 24972 | (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); | ||
| 24973 | |||
| 24974 |
5/8✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 483 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
|
484 | DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", { |
| 24975 | const char act[] = | ||
| 24976 | "now " | ||
| 24977 | "wait_for signal.wsrep_after_BF_victim_lock"; | ||
| 24978 | assert(!debug_sync_set_action(bf_thd, STRING_WITH_LEN(act))); | ||
| 24979 | };); | ||
| 24980 | |||
| 24981 | /* | ||
| 24982 | * we mark with was_chosen_as_deadlock_victim transaction, | ||
| 24983 | * which is already marked as BF victim | ||
| 24984 | * lock_sys is held until this vicitm has aborted | ||
| 24985 | */ | ||
| 24986 |
2/2✓ Branch 0 taken 472 times.
✓ Branch 1 taken 12 times.
|
484 | if (victim_trx->state != TRX_STATE_NOT_STARTED) { |
| 24987 | 472 | victim_trx->lock.was_chosen_as_wsrep_victim = true; | |
| 24988 | } | ||
| 24989 | |||
| 24990 | |||
| 24991 |
2/4✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 484 times.
|
484 | if (wsrep_thd_set_wsrep_aborter(bf_thd, thd)) { |
| 24992 | ✗ | WSREP_DEBUG("innodb kill transaction skipped due to wsrep_aborter set"); | |
| 24993 | ✗ | wsrep_thd_UNLOCK(thd); | |
| 24994 | ✗ | return 0; | |
| 24995 | } | ||
| 24996 | |||
| 24997 |
1/2✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
|
484 | wsrep_thd_UNLOCK(thd); |
| 24998 | |||
| 24999 |
3/4✓ Branch 0 taken 484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 434 times.
✓ Branch 3 taken 50 times.
|
484 | if (wsrep_thd_bf_abort(bf_thd, thd, signal)) { |
| 25000 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 433 times.
|
434 | if (victim_trx->lock.wait_lock) { |
| 25001 |
1/26✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
1 | WSREP_DEBUG( |
| 25002 | "victim: %lu has wait flag(suspended) and will be aborted by" | ||
| 25003 | " lock wait timeout thread", | ||
| 25004 | thd_get_thread_id(thd)); | ||
| 25005 | /* Victim is already marked as interrupted but currently in suspended | ||
| 25006 | state (waiting for lock). The lock wait timeout thread releases the | ||
| 25007 | locks for transactions in interrupted state and wakes up the suspended | ||
| 25008 | thread. See lock_wait_check_and_cancel() */ | ||
| 25009 | } | ||
| 25010 | } else { | ||
| 25011 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | wsrep_thd_LOCK(thd); |
| 25012 | 50 | victim_trx->lock.was_chosen_as_deadlock_victim = false; | |
| 25013 | 50 | victim_trx->lock.was_chosen_as_wsrep_victim = false; | |
| 25014 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | wsrep_thd_set_wsrep_aborter(nullptr, thd); |
| 25015 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | wsrep_thd_UNLOCK(thd); |
| 25016 | |||
| 25017 |
1/24✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
50 | WSREP_DEBUG("wsrep_thd_bf_abort has failed, victim will survive"); |
| 25018 | 50 | return 1; | |
| 25019 | } | ||
| 25020 | |||
| 25021 | 434 | return 0; | |
| 25022 | 484 | } | |
| 25023 | |||
| 25024 | 174 | static int wsrep_abort_transaction_func(handlerton *hton, THD *bf_thd, | |
| 25025 | THD *victim_thd, bool signal) { | ||
| 25026 |
1/2✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
|
174 | DBUG_ENTER("wsrep_innobase_abort_thd"); |
| 25027 | |||
| 25028 | /* Starting MySQL-8.0, same thd will be used to perform dictionary | ||
| 25029 | (or dd) object changes. These objects changes are done using a separate | ||
| 25030 | transaction that is created on the fly. Given the main innodb code | ||
| 25031 | is tuned to look at only 1 transaction object, the main transaction | ||
| 25032 | object needs to be backed up so that this temporary dd transaction object | ||
| 25033 | can be feeded for the said tenure. Once the dd update scope is complete | ||
| 25034 | main transaction object is restored. | ||
| 25035 | All this happens as part of attachable transaction that is member of thd. | ||
| 25036 | In the case below, PXC needs to look at victim transaction but this | ||
| 25037 | transaction could be dd transaction as explained above so PXC should | ||
| 25038 | carefully look for the needed victim transaction. This is needed | ||
| 25039 | as transaction is being accessed outside the main thd context. | ||
| 25040 | BF thd is trying to alter transaction state. | ||
| 25041 | |||
| 25042 | Below call should be mutex protected to avoid allowing victim | ||
| 25043 | thd executing routine to restore main transaction while bf_thd | ||
| 25044 | is in process to findout victim transaction */ | ||
| 25045 |
1/2✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
|
174 | mysql_mutex_lock(&victim_thd->LOCK_wsrep_thd_attachable_trx); |
| 25046 | /* This mutex lock is not needed but keeping it for now as safety check. */ | ||
| 25047 |
1/2✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
|
174 | mysql_mutex_lock(&victim_thd->LOCK_thd_data); |
| 25048 |
1/2✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
|
174 | trx_t *victim_trx = wsrep_thd_to_trx(victim_thd); |
| 25049 |
1/2✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
|
174 | mysql_mutex_unlock(&victim_thd->LOCK_thd_data); |
| 25050 |
1/2✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
|
174 | mysql_mutex_unlock(&victim_thd->LOCK_wsrep_thd_attachable_trx); |
| 25051 | |||
| 25052 | /* mutex lock is not needed here as execution if being done by bf_thd. */ | ||
| 25053 |
2/4✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 174 times.
✗ Branch 3 not taken.
|
174 | trx_t *bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; |
| 25054 |
1/28✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
|
174 | WSREP_DEBUG("Abort Transaction BF query: %s Victim query: %s", |
| 25055 | wsrep_thd_query(bf_thd), wsrep_thd_query(victim_thd)); | ||
| 25056 | |||
| 25057 |
2/2✓ Branch 0 taken 116 times.
✓ Branch 1 taken 58 times.
|
174 | if (victim_trx) { |
| 25058 |
4/8✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 116 times.
✓ Branch 4 taken 116 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 116 times.
✗ Branch 7 not taken.
|
116 | trx_mutex_enter(victim_trx); |
| 25059 |
1/2✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
|
116 | int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx, victim_trx, signal); |
| 25060 |
4/8✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 116 times.
✓ Branch 4 taken 116 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 116 times.
✗ Branch 7 not taken.
|
116 | trx_mutex_exit(victim_trx); |
| 25061 |
1/2✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
|
116 | wsrep_srv_conc_cancel_wait(victim_trx); |
| 25062 | |||
| 25063 |
1/2✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
|
116 | DBUG_RETURN(rcode); |
| 25064 | } else { | ||
| 25065 | /* Normally a background thread that is selected as victim doesn't have | ||
| 25066 | an active transaction associated with it. */ | ||
| 25067 |
1/24✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
58 | WSREP_DEBUG("Victim Thread does not have transaction associated with it"); |
| 25068 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | wsrep_thd_bf_abort(bf_thd, victim_thd, signal); |
| 25069 | } | ||
| 25070 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | DBUG_RETURN(-1); |
| 25071 | } | ||
| 25072 | |||
| 25073 | 15627 | static int innobase_wsrep_set_checkpoint(handlerton *hton, const XID *xid) { | |
| 25074 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15627 times.
|
15627 | assert(hton == innodb_hton_ptr); |
| 25075 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15627 times.
|
15627 | if (srv_read_only_mode) return 0; |
| 25076 |
1/2✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
|
15627 | if (wsrep_is_wsrep_xid(xid)) { |
| 25077 |
1/2✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
|
15627 | mtr_t mtr; |
| 25078 |
1/2✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
|
15627 | mtr_start(&mtr); |
| 25079 |
1/2✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
|
15627 | trx_sysf_t *sys_header = trx_sysf_get(&mtr); |
| 25080 |
1/2✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
|
15627 | trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); |
| 25081 |
1/2✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
|
15627 | mtr_commit(&mtr); |
| 25082 |
1/2✓ Branch 0 taken 15627 times.
✗ Branch 1 not taken.
|
15627 | innobase_flush_logs(hton, false); |
| 25083 | 15627 | return 0; | |
| 25084 | 15627 | } else { | |
| 25085 | ✗ | return 1; | |
| 25086 | } | ||
| 25087 | } | ||
| 25088 | |||
| 25089 | 1442 | static int innobase_wsrep_get_checkpoint(handlerton *hton, XID *xid) { | |
| 25090 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1442 times.
|
1442 | assert(hton == innodb_hton_ptr); |
| 25091 | 1442 | trx_sys_read_wsrep_checkpoint(xid); | |
| 25092 | 1442 | return 0; | |
| 25093 | } | ||
| 25094 | #endif /* WITH_WSREP */ | ||
| 25095 | |||
| 25096 | /* plugin options */ | ||
| 25097 | |||
| 25098 | static MYSQL_SYSVAR_ENUM( | ||
| 25099 | checksum_algorithm, srv_checksum_algorithm, PLUGIN_VAR_RQCMDARG, | ||
| 25100 | "The algorithm InnoDB uses for page checksumming. Possible values are" | ||
| 25101 | " CRC32 (hardware accelerated if the CPU supports it)" | ||
| 25102 | " write crc32, allow any of the other checksums to match when reading;" | ||
| 25103 | " STRICT_CRC32" | ||
| 25104 | " write crc32, do not allow other algorithms to match when reading;" | ||
| 25105 | " INNODB" | ||
| 25106 | " write a software calculated checksum, allow any other checksums" | ||
| 25107 | " to match when reading;" | ||
| 25108 | " STRICT_INNODB" | ||
| 25109 | " write a software calculated checksum, do not allow other algorithms" | ||
| 25110 | " to match when reading;" | ||
| 25111 | " NONE" | ||
| 25112 | " write a constant magic number, do not do any checksum verification" | ||
| 25113 | " when reading;" | ||
| 25114 | " STRICT_NONE" | ||
| 25115 | " write a constant magic number, do not allow values other than that" | ||
| 25116 | " magic number when reading;" | ||
| 25117 | " Files updated when this option is set to crc32 or strict_crc32 will" | ||
| 25118 | " not be readable by MySQL versions older than 5.6.3", | ||
| 25119 | nullptr, nullptr, SRV_CHECKSUM_ALGORITHM_CRC32, | ||
| 25120 | &innodb_checksum_algorithm_typelib); | ||
| 25121 | |||
| 25122 | static MYSQL_SYSVAR_BOOL( | ||
| 25123 | log_checksums, srv_log_checksums, PLUGIN_VAR_RQCMDARG, | ||
| 25124 | "Whether to compute and require checksums for InnoDB redo log blocks", | ||
| 25125 | nullptr, innodb_log_checksums_update, true); | ||
| 25126 | |||
| 25127 | static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir, | ||
| 25128 | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 25129 | "The common part for InnoDB table spaces.", nullptr, | ||
| 25130 | nullptr, nullptr); | ||
| 25131 | |||
| 25132 | static MYSQL_SYSVAR_BOOL( | ||
| 25133 | stats_include_delete_marked, srv_stats_include_delete_marked, | ||
| 25134 | PLUGIN_VAR_OPCMDARG, | ||
| 25135 | "Include delete marked records when calculating persistent statistics", | ||
| 25136 | nullptr, nullptr, false); | ||
| 25137 | |||
| 25138 | static MYSQL_SYSVAR_ULONG( | ||
| 25139 | io_capacity, srv_io_capacity, PLUGIN_VAR_RQCMDARG, | ||
| 25140 | "Number of IOPs the server can do. Tunes the background IO rate", nullptr, | ||
| 25141 | innodb_io_capacity_update, 200, 100, ~0UL, 0); | ||
| 25142 | |||
| 25143 | static MYSQL_SYSVAR_ULONG(io_capacity_max, srv_max_io_capacity, | ||
| 25144 | PLUGIN_VAR_RQCMDARG, | ||
| 25145 | "Limit to which innodb_io_capacity can be inflated.", | ||
| 25146 | nullptr, innodb_io_capacity_max_update, | ||
| 25147 | SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT, 100, | ||
| 25148 | SRV_MAX_IO_CAPACITY_LIMIT, 0); | ||
| 25149 | |||
| 25150 | #ifdef UNIV_DEBUG | ||
| 25151 | static MYSQL_SYSVAR_BOOL(background_drop_list_empty, | ||
| 25152 | innodb_background_drop_list_empty, PLUGIN_VAR_OPCMDARG, | ||
| 25153 | "Wait for the background drop list to become empty", | ||
| 25154 | nullptr, wait_background_drop_list_empty, false); | ||
| 25155 | |||
| 25156 | static MYSQL_SYSVAR_BOOL(purge_run_now, innodb_purge_run_now, | ||
| 25157 | PLUGIN_VAR_OPCMDARG, "Set purge state to RUN", nullptr, | ||
| 25158 | purge_run_now_set, false); | ||
| 25159 | |||
| 25160 | static MYSQL_SYSVAR_BOOL(purge_stop_now, innodb_purge_stop_now, | ||
| 25161 | PLUGIN_VAR_OPCMDARG, "Set purge state to STOP", | ||
| 25162 | nullptr, purge_stop_now_set, false); | ||
| 25163 | |||
| 25164 | static MYSQL_SYSVAR_BOOL(log_flush_now, innodb_log_flush_now, | ||
| 25165 | PLUGIN_VAR_OPCMDARG, | ||
| 25166 | "Force flush of redo up to current lsn", nullptr, | ||
| 25167 | log_flush_now_set, false); | ||
| 25168 | |||
| 25169 | static MYSQL_SYSVAR_BOOL(log_checkpoint_now, innodb_log_checkpoint_now, | ||
| 25170 | PLUGIN_VAR_OPCMDARG, "Force sharp checkpoint now", | ||
| 25171 | nullptr, checkpoint_now_set, false); | ||
| 25172 | |||
| 25173 | static MYSQL_SYSVAR_BOOL(log_checkpoint_fuzzy_now, | ||
| 25174 | innodb_log_checkpoint_fuzzy_now, PLUGIN_VAR_OPCMDARG, | ||
| 25175 | "Force fuzzy checkpoint now", nullptr, | ||
| 25176 | checkpoint_fuzzy_now_set, false); | ||
| 25177 | |||
| 25178 | static MYSQL_SYSVAR_BOOL(checkpoint_disabled, srv_checkpoint_disabled, | ||
| 25179 | PLUGIN_VAR_OPCMDARG, "Disable checkpoints", nullptr, | ||
| 25180 | checkpoint_disabled_update, false); | ||
| 25181 | |||
| 25182 | static MYSQL_SYSVAR_BOOL(buf_flush_list_now, innodb_buf_flush_list_now, | ||
| 25183 | PLUGIN_VAR_OPCMDARG, "Force dirty page flush now", | ||
| 25184 | nullptr, buf_flush_list_now_set, false); | ||
| 25185 | |||
| 25186 | static MYSQL_SYSVAR_UINT( | ||
| 25187 | merge_threshold_set_all_debug, innodb_merge_threshold_set_all_debug, | ||
| 25188 | PLUGIN_VAR_RQCMDARG, | ||
| 25189 | "Override current MERGE_THRESHOLD setting for all indexes at dictionary" | ||
| 25190 | " cache by the specified value dynamically, at the time.", | ||
| 25191 | nullptr, innodb_merge_threshold_set_all_debug_update, | ||
| 25192 | DICT_INDEX_MERGE_THRESHOLD_DEFAULT, 1, 50, 0); | ||
| 25193 | |||
| 25194 | extern ulong srv_fatal_semaphore_wait_threshold; | ||
| 25195 | static MYSQL_SYSVAR_ULONG( | ||
| 25196 | semaphore_wait_timeout_debug, srv_fatal_semaphore_wait_threshold, | ||
| 25197 | PLUGIN_VAR_RQCMDARG, | ||
| 25198 | "Number of seconds that a semaphore can be held. If semaphore wait crosses" | ||
| 25199 | "this value, server will crash", | ||
| 25200 | nullptr, nullptr, 600, 25, 600, 0); | ||
| 25201 | #endif /* UNIV_DEBUG */ | ||
| 25202 | |||
| 25203 | static MYSQL_SYSVAR_ULONG( | ||
| 25204 | purge_batch_size, srv_purge_batch_size, PLUGIN_VAR_OPCMDARG, | ||
| 25205 | "Number of UNDO log pages to purge in one batch from the history list.", | ||
| 25206 | nullptr, nullptr, 300, /* Default setting */ | ||
| 25207 | 1, /* Minimum value */ | ||
| 25208 | 5000, 0); /* Maximum value */ | ||
| 25209 | |||
| 25210 | static MYSQL_SYSVAR_ULONG(purge_threads, srv_n_purge_threads, | ||
| 25211 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 25212 | "Purge threads can be from 1 to 32. Default is 4.", | ||
| 25213 | nullptr, nullptr, 4, /* Default setting */ | ||
| 25214 | 1, /* Minimum value */ | ||
| 25215 | MAX_PURGE_THREADS, 0); /* Maximum value */ | ||
| 25216 | |||
| 25217 | static MYSQL_SYSVAR_ULONG(sync_array_size, srv_sync_array_size, | ||
| 25218 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 25219 | "Size of the mutex/lock wait array.", nullptr, | ||
| 25220 | nullptr, 1, /* Default setting */ | ||
| 25221 | 1, /* Minimum value */ | ||
| 25222 | 1024, 0); /* Maximum value */ | ||
| 25223 | |||
| 25224 | static MYSQL_SYSVAR_ULONG( | ||
| 25225 | fast_shutdown, srv_fast_shutdown, PLUGIN_VAR_OPCMDARG, | ||
| 25226 | "Speeds up the shutdown process of the InnoDB storage engine. Possible" | ||
| 25227 | " values are 0, 1 (faster) or 2 (fastest - crash-like).", | ||
| 25228 | nullptr, nullptr, 1, 0, 2, 0); | ||
| 25229 | |||
| 25230 | static MYSQL_SYSVAR_BOOL( | ||
| 25231 | file_per_table, srv_file_per_table, PLUGIN_VAR_NOCMDARG, | ||
| 25232 | "Stores each InnoDB table to an .ibd file in the database dir.", nullptr, | ||
| 25233 | nullptr, true); | ||
| 25234 | |||
| 25235 | static MYSQL_SYSVAR_STR(ft_server_stopword_table, | ||
| 25236 | innobase_server_stopword_table, | ||
| 25237 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 25238 | "The user supplied stopword table name.", | ||
| 25239 | innodb_stopword_table_validate, nullptr, nullptr); | ||
| 25240 | |||
| 25241 | extern uint srv_flush_log_at_timeout; | ||
| 25242 | static MYSQL_SYSVAR_UINT(flush_log_at_timeout, srv_flush_log_at_timeout, | ||
| 25243 | PLUGIN_VAR_OPCMDARG, | ||
| 25244 | "Write and flush logs every (n) second.", nullptr, | ||
| 25245 | nullptr, 1, 0, 2700, 0); | ||
| 25246 | |||
| 25247 | static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit, | ||
| 25248 | PLUGIN_VAR_OPCMDARG, | ||
| 25249 | "Set to 0 (write and flush once per second)," | ||
| 25250 | " 1 (write and flush at each commit)," | ||
| 25251 | " or 2 (write at commit, flush once per second).", | ||
| 25252 | nullptr, nullptr, 1, 0, 2, 0); | ||
| 25253 | |||
| 25254 | static MYSQL_SYSVAR_ENUM(flush_method, innodb_flush_method, | ||
| 25255 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25256 | "With which method to flush data", nullptr, nullptr, 0, | ||
| 25257 | &innodb_flush_method_typelib); | ||
| 25258 | |||
| 25259 | static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted, | ||
| 25260 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY | | ||
| 25261 | PLUGIN_VAR_NOPERSIST, | ||
| 25262 | "Force InnoDB to load metadata of corrupted table.", | ||
| 25263 | nullptr, nullptr, false); | ||
| 25264 | |||
| 25265 | static MYSQL_SYSVAR_ULONG(show_locks_held, srv_show_locks_held, | ||
| 25266 | PLUGIN_VAR_RQCMDARG, | ||
| 25267 | "Number of locks held to print for each InnoDB " | ||
| 25268 | "transaction in SHOW INNODB STATUS.", | ||
| 25269 | NULL, NULL, 10, 0, 1000, 0); | ||
| 25270 | |||
| 25271 | static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir, | ||
| 25272 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | | ||
| 25273 | PLUGIN_VAR_NOPERSIST, | ||
| 25274 | "Path to InnoDB log files.", nullptr, nullptr, nullptr); | ||
| 25275 | |||
| 25276 | static MYSQL_SYSVAR_ULONG( | ||
| 25277 | page_cleaners, srv_n_page_cleaners, | ||
| 25278 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 25279 | "Page cleaner threads can be from 1 to 64. Default is 4.", nullptr, nullptr, | ||
| 25280 | 4, 1, 64, 0); | ||
| 25281 | |||
| 25282 | static MYSQL_SYSVAR_DOUBLE(max_dirty_pages_pct, srv_max_buf_pool_modified_pct, | ||
| 25283 | PLUGIN_VAR_RQCMDARG, | ||
| 25284 | "Percentage of dirty pages allowed in bufferpool.", | ||
| 25285 | nullptr, innodb_max_dirty_pages_pct_update, 90.0, 0, | ||
| 25286 | 99.999, 0); | ||
| 25287 | |||
| 25288 | static MYSQL_SYSVAR_DOUBLE( | ||
| 25289 | max_dirty_pages_pct_lwm, srv_max_dirty_pages_pct_lwm, PLUGIN_VAR_RQCMDARG, | ||
| 25290 | "Percentage of dirty pages at which flushing kicks in.", nullptr, | ||
| 25291 | innodb_max_dirty_pages_pct_lwm_update, 10, 0, 99.999, 0); | ||
| 25292 | |||
| 25293 | static MYSQL_SYSVAR_ULONG( | ||
| 25294 | adaptive_flushing_lwm, srv_adaptive_flushing_lwm, PLUGIN_VAR_RQCMDARG, | ||
| 25295 | "Percentage of log capacity below which no adaptive flushing happens.", | ||
| 25296 | nullptr, nullptr, 10, 0, 70, 0); | ||
| 25297 | |||
| 25298 | static MYSQL_SYSVAR_BOOL( | ||
| 25299 | adaptive_flushing, srv_adaptive_flushing, PLUGIN_VAR_NOCMDARG, | ||
| 25300 | "Attempt flushing dirty pages to avoid IO bursts at checkpoints.", nullptr, | ||
| 25301 | nullptr, true); | ||
| 25302 | |||
| 25303 | static MYSQL_SYSVAR_BOOL( | ||
| 25304 | flush_sync, srv_flush_sync, PLUGIN_VAR_NOCMDARG, | ||
| 25305 | "Allow IO bursts at the checkpoints ignoring io_capacity setting.", nullptr, | ||
| 25306 | nullptr, true); | ||
| 25307 | |||
| 25308 | static MYSQL_SYSVAR_ULONG( | ||
| 25309 | flushing_avg_loops, srv_flushing_avg_loops, PLUGIN_VAR_RQCMDARG, | ||
| 25310 | "Number of iterations over which the background flushing is averaged.", | ||
| 25311 | nullptr, nullptr, 30, 1, 1000, 0); | ||
| 25312 | |||
| 25313 | static MYSQL_SYSVAR_ULONG( | ||
| 25314 | max_purge_lag, srv_max_purge_lag, PLUGIN_VAR_RQCMDARG, | ||
| 25315 | "Desired maximum length of the purge queue (0 = no limit)", nullptr, | ||
| 25316 | nullptr, 0, 0, ~0UL, 0); | ||
| 25317 | |||
| 25318 | static MYSQL_SYSVAR_ULONG(max_purge_lag_delay, srv_max_purge_lag_delay, | ||
| 25319 | PLUGIN_VAR_RQCMDARG, | ||
| 25320 | "Maximum delay of user threads in micro-seconds", | ||
| 25321 | nullptr, nullptr, 0L, /* Default seting */ | ||
| 25322 | 0L, /* Minimum value */ | ||
| 25323 | 10000000UL, 0); /* Maximum value */ | ||
| 25324 | |||
| 25325 | static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout, | ||
| 25326 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 25327 | "Roll back the complete transaction on lock wait " | ||
| 25328 | "timeout, for 4.x compatibility (disabled by default)", | ||
| 25329 | nullptr, nullptr, false); | ||
| 25330 | |||
| 25331 | static MYSQL_SYSVAR_BOOL( | ||
| 25332 | status_file, innobase_create_status_file, | ||
| 25333 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR, | ||
| 25334 | "Enable SHOW ENGINE INNODB STATUS output in the innodb_status.<pid> file", | ||
| 25335 | nullptr, nullptr, false); | ||
| 25336 | |||
| 25337 | static MYSQL_SYSVAR_BOOL( | ||
| 25338 | stats_on_metadata, innobase_stats_on_metadata, PLUGIN_VAR_OPCMDARG, | ||
| 25339 | "Enable statistics gathering for metadata commands such as" | ||
| 25340 | " SHOW TABLE STATUS for tables that use transient statistics (off by " | ||
| 25341 | "default)", | ||
| 25342 | nullptr, nullptr, false); | ||
| 25343 | |||
| 25344 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 25345 | stats_transient_sample_pages, srv_stats_transient_sample_pages, | ||
| 25346 | PLUGIN_VAR_RQCMDARG, | ||
| 25347 | "The number of leaf index pages to sample when calculating transient" | ||
| 25348 | " statistics (if persistent statistics are not used, default 8)", | ||
| 25349 | nullptr, nullptr, 8, 1, ~0ULL, 0); | ||
| 25350 | |||
| 25351 | static MYSQL_SYSVAR_BOOL( | ||
| 25352 | stats_persistent, srv_stats_persistent, PLUGIN_VAR_OPCMDARG, | ||
| 25353 | "InnoDB persistent statistics enabled for all tables unless overridden" | ||
| 25354 | " at table level", | ||
| 25355 | nullptr, nullptr, true); | ||
| 25356 | |||
| 25357 | static MYSQL_SYSVAR_BOOL( | ||
| 25358 | stats_auto_recalc, srv_stats_auto_recalc, PLUGIN_VAR_OPCMDARG, | ||
| 25359 | "InnoDB automatic recalculation of persistent statistics enabled for all" | ||
| 25360 | " tables unless overridden at table level (automatic recalculation is only" | ||
| 25361 | " done when InnoDB decides that the table has changed too much and needs a" | ||
| 25362 | " new statistics)", | ||
| 25363 | nullptr, nullptr, true); | ||
| 25364 | |||
| 25365 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 25366 | stats_persistent_sample_pages, srv_stats_persistent_sample_pages, | ||
| 25367 | PLUGIN_VAR_RQCMDARG, | ||
| 25368 | "The number of leaf index pages to sample when calculating persistent" | ||
| 25369 | " statistics (by ANALYZE, default 20)", | ||
| 25370 | nullptr, nullptr, 20, 1, ~0ULL, 0); | ||
| 25371 | |||
| 25372 | static MYSQL_SYSVAR_BOOL( | ||
| 25373 | adaptive_hash_index, btr_search_enabled, PLUGIN_VAR_OPCMDARG, | ||
| 25374 | "Enable InnoDB adaptive hash index (enabled by default). " | ||
| 25375 | " Disable with --skip-innodb-adaptive-hash-index.", | ||
| 25376 | nullptr, innodb_adaptive_hash_index_update, true); | ||
| 25377 | |||
| 25378 | /** Number of distinct partitions of AHI. | ||
| 25379 | Each partition is protected by its own latch and so we have parts number | ||
| 25380 | of latches protecting complete search system. */ | ||
| 25381 | static MYSQL_SYSVAR_ULONG( | ||
| 25382 | adaptive_hash_index_parts, btr_ahi_parts, | ||
| 25383 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 25384 | "Number of InnoDB Adaptive Hash Index Partitions. (default = 8). ", nullptr, | ||
| 25385 | nullptr, 8, 1, 512, 0); | ||
| 25386 | |||
| 25387 | extern ulong srv_replication_delay; | ||
| 25388 | static MYSQL_SYSVAR_ULONG( | ||
| 25389 | replication_delay, srv_replication_delay, PLUGIN_VAR_RQCMDARG, | ||
| 25390 | "Replication thread delay (ms) on the slave server if" | ||
| 25391 | " innodb_thread_concurrency is reached (0 by default)", | ||
| 25392 | nullptr, nullptr, 0, 0, ~0UL, 0); | ||
| 25393 | |||
| 25394 | static MYSQL_SYSVAR_UINT( | ||
| 25395 | compression_level, page_zip_level, PLUGIN_VAR_RQCMDARG, | ||
| 25396 | "Compression level used for compressed row format. 0 is no compression" | ||
| 25397 | ", 1 is fastest, 9 is best compression and default is 6.", | ||
| 25398 | nullptr, nullptr, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0); | ||
| 25399 | |||
| 25400 | static MYSQL_SYSVAR_BOOL( | ||
| 25401 | log_compressed_pages, page_zip_log_pages, PLUGIN_VAR_OPCMDARG, | ||
| 25402 | "Enables/disables the logging of entire compressed page images." | ||
| 25403 | " InnoDB logs the compressed pages to prevent corruption if" | ||
| 25404 | " the zlib compression algorithm changes." | ||
| 25405 | " When turned OFF, InnoDB will assume that the zlib" | ||
| 25406 | " compression algorithm doesn't change.", | ||
| 25407 | nullptr, nullptr, true); | ||
| 25408 | |||
| 25409 | static MYSQL_SYSVAR_ULONG(autoextend_increment, | ||
| 25410 | sys_tablespace_auto_extend_increment, | ||
| 25411 | PLUGIN_VAR_RQCMDARG, | ||
| 25412 | "Data file autoextend increment in megabytes", | ||
| 25413 | nullptr, nullptr, 64L, 1L, 1000L, 0); | ||
| 25414 | |||
| 25415 | static MYSQL_SYSVAR_BOOL( | ||
| 25416 | dedicated_server, srv_dedicated_server, | ||
| 25417 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOPERSIST | PLUGIN_VAR_READONLY, | ||
| 25418 | "Automatically scale innodb_buffer_pool_size and innodb_redo_log_capacity " | ||
| 25419 | "based on system memory. Also set innodb_flush_method=O_DIRECT_NO_FSYNC, " | ||
| 25420 | "if supported", | ||
| 25421 | nullptr, nullptr, false); | ||
| 25422 | |||
| 25423 | static MYSQL_SYSVAR_DOUBLE( | ||
| 25424 | segment_reserve_factor, fseg_reserve_pct, PLUGIN_VAR_OPCMDARG, | ||
| 25425 | "The segment_reserve_factor is the ratio x/y expressed in percentage," | ||
| 25426 | " where x is the number of free pages in the segment, and y is the total" | ||
| 25427 | " number of pages in the segment. The number of used pages in the segment" | ||
| 25428 | " is given by (y-x). The number of free pages in the segment (x) will be" | ||
| 25429 | " maintained such that the actual segment_reserve_factor will be >= the" | ||
| 25430 | " requested segment_reserve_factor, which is contained in this variable.", | ||
| 25431 | nullptr, nullptr, FSEG_RESERVE_PCT_DFLT, FSEG_RESERVE_PCT_MIN, | ||
| 25432 | FSEG_RESERVE_PCT_MAX, 0); | ||
| 25433 | |||
| 25434 | /* If the default value of innodb_buffer_pool_size is increased to be more than | ||
| 25435 | BUF_POOL_SIZE_THRESHOLD (srv/srv0start.cc), then srv_buf_pool_instances_default | ||
| 25436 | can be removed and 8 used instead. The problem with the current setup is that | ||
| 25437 | with 128MiB default buffer pool size and 8 instances by default we would emit | ||
| 25438 | a warning when no options are specified. */ | ||
| 25439 | static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, srv_buf_pool_curr_size, | ||
| 25440 | PLUGIN_VAR_RQCMDARG | | ||
| 25441 | PLUGIN_VAR_PERSIST_AS_READ_ONLY, | ||
| 25442 | "The size of the memory buffer InnoDB uses to " | ||
| 25443 | "cache data and indexes of its tables.", | ||
| 25444 | nullptr, innodb_buffer_pool_size_update, | ||
| 25445 | static_cast<longlong>(srv_buf_pool_def_size), | ||
| 25446 | static_cast<longlong>(srv_buf_pool_min_size), | ||
| 25447 | longlong{srv_buf_pool_max_size}, 1024 * 1024L); | ||
| 25448 | |||
| 25449 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 25450 | buffer_pool_chunk_size, srv_buf_pool_chunk_unit, | ||
| 25451 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25452 | "Size of a single memory chunk within each buffer pool instance" | ||
| 25453 | " for resizing buffer pool. Online buffer pool resizing happens" | ||
| 25454 | " at this granularity.", | ||
| 25455 | nullptr, nullptr, 128 * 1024 * 1024, ulonglong{srv_buf_pool_chunk_unit_min}, | ||
| 25456 | ulonglong{srv_buf_pool_chunk_unit_max}, | ||
| 25457 | ulonglong{srv_buf_pool_chunk_unit_blk_sz}); | ||
| 25458 | |||
| 25459 | #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG | ||
| 25460 | static MYSQL_SYSVAR_ULONG(page_hash_locks, srv_n_page_hash_locks, | ||
| 25461 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 25462 | "Number of rw_locks protecting buffer pool " | ||
| 25463 | "page_hash. Rounded up to the next power of 2", | ||
| 25464 | nullptr, nullptr, 16, 1, MAX_PAGE_HASH_LOCKS, 0); | ||
| 25465 | |||
| 25466 | #ifdef UNIV_LINUX | ||
| 25467 | |||
| 25468 | static MYSQL_SYSVAR_ULONG(sched_priority_purge, srv_sched_priority_purge, | ||
| 25469 | PLUGIN_VAR_RQCMDARG, | ||
| 25470 | "Nice value for the purge thread scheduling", NULL, | ||
| 25471 | innodb_sched_priority_purge_update, 19, 0, 39, 0); | ||
| 25472 | |||
| 25473 | static MYSQL_SYSVAR_ULONG(sched_priority_io, srv_sched_priority_io, | ||
| 25474 | PLUGIN_VAR_RQCMDARG, | ||
| 25475 | "Nice value for the I/O handler thread scheduling", | ||
| 25476 | NULL, innodb_sched_priority_io_update, 19, 0, 39, 0); | ||
| 25477 | |||
| 25478 | static MYSQL_SYSVAR_ULONG(sched_priority_master, srv_sched_priority_master, | ||
| 25479 | PLUGIN_VAR_RQCMDARG, | ||
| 25480 | "Nice value for the master thread scheduling", NULL, | ||
| 25481 | innodb_sched_priority_master_update, 19, 0, 39, 0); | ||
| 25482 | |||
| 25483 | static MYSQL_SYSVAR_BOOL( | ||
| 25484 | priority_purge, srv_purge_thread_priority, PLUGIN_VAR_OPCMDARG, | ||
| 25485 | "Make purge coordinator and worker threads acquire shared resources with " | ||
| 25486 | "priority", | ||
| 25487 | NULL, NULL, false); | ||
| 25488 | |||
| 25489 | static MYSQL_SYSVAR_BOOL( | ||
| 25490 | priority_master, srv_master_thread_priority, PLUGIN_VAR_OPCMDARG, | ||
| 25491 | "Make buffer pool cleaner thread acquire shared resources with priority", | ||
| 25492 | NULL, NULL, false); | ||
| 25493 | |||
| 25494 | #endif /* UNIV_LINUX */ | ||
| 25495 | |||
| 25496 | // TODO: the option is here, but currently a no-op | ||
| 25497 | static MYSQL_SYSVAR_ULONG( | ||
| 25498 | cleaner_max_lru_time, srv_cleaner_max_lru_time, PLUGIN_VAR_RQCMDARG, | ||
| 25499 | "The maximum time limit for a single LRU tail flush iteration by the page " | ||
| 25500 | "cleaner thread in miliseconds", | ||
| 25501 | NULL, NULL, 1000, 0, ~0UL, 0); | ||
| 25502 | |||
| 25503 | // TODO: the option is here, but currently a no-op | ||
| 25504 | static MYSQL_SYSVAR_ULONG(cleaner_max_flush_time, srv_cleaner_max_flush_time, | ||
| 25505 | PLUGIN_VAR_RQCMDARG, | ||
| 25506 | "The maximum time limit for a single flush list " | ||
| 25507 | "flush iteration by the page " | ||
| 25508 | "cleaner thread in miliseconds", | ||
| 25509 | NULL, NULL, 1000, 0, ~0UL, 0); | ||
| 25510 | #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */ | ||
| 25511 | |||
| 25512 | static MYSQL_SYSVAR_BOOL( | ||
| 25513 | validate_tablespace_paths, srv_validate_tablespace_paths, | ||
| 25514 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 25515 | "Enable validation of tablespace paths against the DD. (enabled by " | ||
| 25516 | "default)." | ||
| 25517 | " Disable with --skip-innodb-validate-tablespace-paths.", | ||
| 25518 | nullptr, nullptr, true); | ||
| 25519 | |||
| 25520 | static MYSQL_SYSVAR_BOOL(use_fdatasync, srv_use_fdatasync, PLUGIN_VAR_NOCMDARG, | ||
| 25521 | "Use fdatasync() instead of the default fsync().", | ||
| 25522 | nullptr, nullptr, false); | ||
| 25523 | |||
| 25524 | // clang-format off | ||
| 25525 | static MYSQL_SYSVAR_ENUM( | ||
| 25526 | doublewrite, dblwr::g_mode, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 25527 | "Enable InnoDB doublewrite buffer (enabled by default)." | ||
| 25528 | " Disable with --skip-innodb-doublewrite.", | ||
| 25529 | nullptr, doublewrite_update, dblwr::Mode::ON, &innodb_doublewrite_typelib); | ||
| 25530 | |||
| 25531 | static MYSQL_SYSVAR_BOOL( | ||
| 25532 | extend_and_initialize, tbsp_extend_and_initialize, PLUGIN_VAR_NOCMDARG, | ||
| 25533 | "Initialize the allocated space by writing zeros (enabled by default).", | ||
| 25534 | nullptr, innodb_extend_and_initialize_update, true); | ||
| 25535 | |||
| 25536 | static MYSQL_SYSVAR_STR( | ||
| 25537 | doublewrite_dir, innobase_doublewrite_dir, PLUGIN_VAR_READONLY, | ||
| 25538 | "Use a separate directory for the doublewrite buffer files, ", nullptr, nullptr, | ||
| 25539 | nullptr); | ||
| 25540 | |||
| 25541 | static MYSQL_SYSVAR_ULONG( | ||
| 25542 | doublewrite_pages, dblwr::n_pages, | ||
| 25543 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25544 | "Number of double write pages per thread" , nullptr, nullptr, 0, 0, 512, 0); | ||
| 25545 | |||
| 25546 | static MYSQL_SYSVAR_ULONG( | ||
| 25547 | doublewrite_files, dblwr::n_files, | ||
| 25548 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25549 | "Number of double write files", nullptr, nullptr, 0, 0, 256, 0); | ||
| 25550 | |||
| 25551 | static MYSQL_SYSVAR_ULONG( | ||
| 25552 | doublewrite_batch_size, dblwr::batch_size, | ||
| 25553 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25554 | "Number of double write pages to write in a batch", nullptr, nullptr, | ||
| 25555 | 0, 0, 256, 0); | ||
| 25556 | // clang-format on | ||
| 25557 | |||
| 25558 | static MYSQL_SYSVAR_ENUM( | ||
| 25559 | cleaner_lsn_age_factor, srv_cleaner_lsn_age_factor, PLUGIN_VAR_OPCMDARG, | ||
| 25560 | "The formula for LSN age factor for page cleaner adaptive flushing. " | ||
| 25561 | "LEGACY: Original Oracle MySQL formula. " | ||
| 25562 | "HIGH_CHECKPOINT: (the default) Percona Server formula.", | ||
| 25563 | nullptr, nullptr, SRV_CLEANER_LSN_AGE_FACTOR_HIGH_CHECKPOINT, | ||
| 25564 | &innodb_cleaner_lsn_age_factor_typelib); | ||
| 25565 | |||
| 25566 | static MYSQL_SYSVAR_ENUM( | ||
| 25567 | empty_free_list_algorithm, srv_empty_free_list_algorithm, | ||
| 25568 | PLUGIN_VAR_OPCMDARG, | ||
| 25569 | "The algorithm to use for empty free list handling. Allowed values: " | ||
| 25570 | "LEGACY: (the default) Original Oracle MySQL handling with single page " | ||
| 25571 | "flushes; " | ||
| 25572 | "BACKOFF: Wait until cleaner produces a free page.", | ||
| 25573 | innodb_srv_empty_free_list_algorithm_validate, nullptr, | ||
| 25574 | SRV_EMPTY_FREE_LIST_LEGACY, &innodb_empty_free_list_algorithm_typelib); | ||
| 25575 | |||
| 25576 | static MYSQL_SYSVAR_ULONG(buffer_pool_instances, srv_buf_pool_instances, | ||
| 25577 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25578 | "Number of buffer pool instances, set to higher " | ||
| 25579 | "value on high-end machines to increase scalability", | ||
| 25580 | nullptr, nullptr, srv_buf_pool_instances_default, 0, | ||
| 25581 | MAX_BUFFER_POOLS, 0); | ||
| 25582 | |||
| 25583 | static MYSQL_SYSVAR_STR( | ||
| 25584 | buffer_pool_filename, srv_buf_dump_filename, | ||
| 25585 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 25586 | "Filename to/from which to dump/load the InnoDB buffer pool", | ||
| 25587 | innodb_srv_buf_dump_filename_validate, nullptr, | ||
| 25588 | SRV_BUF_DUMP_FILENAME_DEFAULT); | ||
| 25589 | |||
| 25590 | static MYSQL_SYSVAR_BOOL(buffer_pool_dump_now, innodb_buffer_pool_dump_now, | ||
| 25591 | PLUGIN_VAR_RQCMDARG, | ||
| 25592 | "Trigger an immediate dump of the buffer pool into a " | ||
| 25593 | "file named @@innodb_buffer_pool_filename", | ||
| 25594 | nullptr, buffer_pool_dump_now, false); | ||
| 25595 | |||
| 25596 | static MYSQL_SYSVAR_BOOL( | ||
| 25597 | buffer_pool_dump_at_shutdown, srv_buffer_pool_dump_at_shutdown, | ||
| 25598 | PLUGIN_VAR_RQCMDARG, | ||
| 25599 | "Dump the buffer pool into a file named @@innodb_buffer_pool_filename", | ||
| 25600 | nullptr, nullptr, true); | ||
| 25601 | |||
| 25602 | static MYSQL_SYSVAR_BOOL( | ||
| 25603 | buffer_pool_in_core_file, srv_buffer_pool_in_core_file, PLUGIN_VAR_NOCMDARG, | ||
| 25604 | "This option has no effect if @@core_file is OFF. " | ||
| 25605 | "If @@core_file is ON, and this option is OFF, then the core dump file will" | ||
| 25606 | " be generated only if it is possible to exclude buffer pool from it. " | ||
| 25607 | "As soon as it will be determined that such exclusion is impossible a " | ||
| 25608 | "warning will be emitted and @@core_file will be set to OFF to prevent " | ||
| 25609 | "generating a core dump. " | ||
| 25610 | "If this option is enabled (which is the default), then core dumping " | ||
| 25611 | "logic will not be affected. ", | ||
| 25612 | nullptr, innodb_srv_buffer_pool_in_core_file_update, true); | ||
| 25613 | |||
| 25614 | static MYSQL_SYSVAR_ULONG( | ||
| 25615 | buffer_pool_dump_pct, srv_buf_pool_dump_pct, PLUGIN_VAR_RQCMDARG, | ||
| 25616 | "Dump only the hottest N% of each buffer pool, defaults to 25", nullptr, | ||
| 25617 | nullptr, 25, 1, 100, 0); | ||
| 25618 | |||
| 25619 | static MYSQL_SYSVAR_ULONG( | ||
| 25620 | idle_flush_pct, srv_idle_flush_pct, PLUGIN_VAR_RQCMDARG, | ||
| 25621 | "Up to what percentage of dirty pages to be flushed when server is found" | ||
| 25622 | " idle.", | ||
| 25623 | nullptr, nullptr, srv_idle_flush_pct_default, 0, 100, 0); | ||
| 25624 | |||
| 25625 | #ifdef UNIV_DEBUG | ||
| 25626 | static MYSQL_SYSVAR_STR(buffer_pool_evict, srv_buffer_pool_evict, | ||
| 25627 | PLUGIN_VAR_RQCMDARG, "Evict pages from the buffer pool", | ||
| 25628 | nullptr, innodb_buffer_pool_evict_update, ""); | ||
| 25629 | #endif /* UNIV_DEBUG */ | ||
| 25630 | |||
| 25631 | static MYSQL_SYSVAR_BOOL(buffer_pool_load_now, innodb_buffer_pool_load_now, | ||
| 25632 | PLUGIN_VAR_RQCMDARG, | ||
| 25633 | "Trigger an immediate load of the buffer pool from a " | ||
| 25634 | "file named @@innodb_buffer_pool_filename", | ||
| 25635 | nullptr, buffer_pool_load_now, false); | ||
| 25636 | |||
| 25637 | static MYSQL_SYSVAR_BOOL(buffer_pool_load_abort, innodb_buffer_pool_load_abort, | ||
| 25638 | PLUGIN_VAR_RQCMDARG, | ||
| 25639 | "Abort a currently running load of the buffer pool", | ||
| 25640 | nullptr, buffer_pool_load_abort, false); | ||
| 25641 | |||
| 25642 | /* there is no point in changing this during runtime, thus readonly */ | ||
| 25643 | static MYSQL_SYSVAR_BOOL( | ||
| 25644 | buffer_pool_load_at_startup, srv_buffer_pool_load_at_startup, | ||
| 25645 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 25646 | "Load the buffer pool from a file named @@innodb_buffer_pool_filename", | ||
| 25647 | nullptr, nullptr, true); | ||
| 25648 | |||
| 25649 | static MYSQL_SYSVAR_ULONG(lru_scan_depth, srv_LRU_scan_depth, | ||
| 25650 | PLUGIN_VAR_RQCMDARG, | ||
| 25651 | "How deep to scan LRU to keep it clean", nullptr, | ||
| 25652 | nullptr, 1024, 100, ~0UL, 0); | ||
| 25653 | |||
| 25654 | static MYSQL_SYSVAR_ULONG(flush_neighbors, srv_flush_neighbors, | ||
| 25655 | PLUGIN_VAR_OPCMDARG, | ||
| 25656 | "Set to 0 (don't flush neighbors from buffer pool)," | ||
| 25657 | " 1 (flush contiguous neighbors from buffer pool)" | ||
| 25658 | " or 2 (flush neighbors from buffer pool)," | ||
| 25659 | " when flushing a block", | ||
| 25660 | nullptr, nullptr, 0, 0, 2, 0); | ||
| 25661 | |||
| 25662 | static MYSQL_SYSVAR_ULONG( | ||
| 25663 | commit_concurrency, innobase_commit_concurrency, PLUGIN_VAR_RQCMDARG, | ||
| 25664 | "Helps in performance tuning in heavily concurrent environments.", | ||
| 25665 | innobase_commit_concurrency_validate, nullptr, 0, 0, 1000, 0); | ||
| 25666 | |||
| 25667 | static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter, | ||
| 25668 | PLUGIN_VAR_RQCMDARG, | ||
| 25669 | "Number of times a thread is allowed to enter InnoDB " | ||
| 25670 | "within the same SQL query after it has once got the " | ||
| 25671 | "ticket", | ||
| 25672 | nullptr, nullptr, 5000L, 1L, UINT_MAX, 0); | ||
| 25673 | |||
| 25674 | static MYSQL_SYSVAR_BOOL( | ||
| 25675 | deadlock_detect, innobase_deadlock_detect, PLUGIN_VAR_NOCMDARG, | ||
| 25676 | "Enable/disable InnoDB deadlock detector (default ON)." | ||
| 25677 | " if set to OFF, deadlock detection is skipped," | ||
| 25678 | " and we rely on innodb_lock_wait_timeout in case of deadlock.", | ||
| 25679 | nullptr, innobase_deadlock_detect_update, true); | ||
| 25680 | |||
| 25681 | static MYSQL_SYSVAR_LONG(fill_factor, ddl::fill_factor, PLUGIN_VAR_RQCMDARG, | ||
| 25682 | "Percentage of B-tree page filled during bulk insert", | ||
| 25683 | nullptr, nullptr, 100, 10, 100, 0); | ||
| 25684 | |||
| 25685 | static MYSQL_SYSVAR_BOOL( | ||
| 25686 | ft_enable_diag_print, fts_enable_diag_print, PLUGIN_VAR_OPCMDARG, | ||
| 25687 | "Whether to enable additional FTS diagnostic printout ", nullptr, nullptr, | ||
| 25688 | false); | ||
| 25689 | |||
| 25690 | static MYSQL_SYSVAR_BOOL(disable_sort_file_cache, srv_disable_sort_file_cache, | ||
| 25691 | PLUGIN_VAR_OPCMDARG, | ||
| 25692 | "Whether to disable OS system file cache for sort I/O", | ||
| 25693 | nullptr, nullptr, false); | ||
| 25694 | |||
| 25695 | static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name, | ||
| 25696 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 25697 | "FTS internal auxiliary table to be checked", | ||
| 25698 | innodb_internal_table_validate, nullptr, nullptr); | ||
| 25699 | |||
| 25700 | static MYSQL_SYSVAR_ULONG(ft_cache_size, fts_max_cache_size, | ||
| 25701 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25702 | "InnoDB Fulltext search cache size in bytes", nullptr, | ||
| 25703 | nullptr, 8000000, 1600000, 80000000, 0); | ||
| 25704 | |||
| 25705 | static MYSQL_SYSVAR_ULONG( | ||
| 25706 | ft_total_cache_size, fts_max_total_cache_size, | ||
| 25707 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25708 | "Total memory allocated for InnoDB Fulltext Search cache", nullptr, nullptr, | ||
| 25709 | 640000000, 32000000, 1600000000, 0); | ||
| 25710 | |||
| 25711 | static MYSQL_SYSVAR_ULONG( | ||
| 25712 | ft_result_cache_limit, fts_result_cache_limit, PLUGIN_VAR_RQCMDARG, | ||
| 25713 | "InnoDB Fulltext search query result cache limit in bytes", nullptr, | ||
| 25714 | nullptr, 2000000000L, 1000000L, 4294967295UL, 0); | ||
| 25715 | |||
| 25716 | static MYSQL_SYSVAR_ULONG( | ||
| 25717 | ft_min_token_size, fts_min_token_size, | ||
| 25718 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25719 | "InnoDB Fulltext search minimum token size in characters", nullptr, nullptr, | ||
| 25720 | 3, 0, 16, 0); | ||
| 25721 | |||
| 25722 | static MYSQL_SYSVAR_ULONG( | ||
| 25723 | ft_max_token_size, fts_max_token_size, | ||
| 25724 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25725 | "InnoDB Fulltext search maximum token size in characters", nullptr, nullptr, | ||
| 25726 | FTS_MAX_WORD_LEN_IN_CHAR, 10, FTS_MAX_WORD_LEN_IN_CHAR, 0); | ||
| 25727 | |||
| 25728 | static MYSQL_SYSVAR_ULONG(ft_num_word_optimize, fts_num_word_optimize, | ||
| 25729 | PLUGIN_VAR_OPCMDARG, | ||
| 25730 | "InnoDB Fulltext search number of words to optimize " | ||
| 25731 | "for each optimize table call ", | ||
| 25732 | nullptr, nullptr, 2000, 1000, 10000, 0); | ||
| 25733 | |||
| 25734 | static MYSQL_SYSVAR_ULONG(ft_sort_pll_degree, ddl::fts_parser_threads, | ||
| 25735 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25736 | "InnoDB Fulltext search parallel sort degree, will " | ||
| 25737 | "round up to nearest power of 2 number", | ||
| 25738 | nullptr, nullptr, 2, 1, 16, 0); | ||
| 25739 | |||
| 25740 | static MYSQL_SYSVAR_ULONG(sort_buffer_size, srv_sort_buf_size, | ||
| 25741 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25742 | "Memory buffer size for index creation", nullptr, | ||
| 25743 | nullptr, 1048576, 65536, 64 << 20, 0); | ||
| 25744 | |||
| 25745 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 25746 | online_alter_log_max_size, srv_online_max_size, PLUGIN_VAR_RQCMDARG, | ||
| 25747 | "Maximum modification log file size for online index creation", nullptr, | ||
| 25748 | nullptr, 128 << 20, 65536, ~0ULL, 0); | ||
| 25749 | |||
| 25750 | static MYSQL_SYSVAR_BOOL(optimize_fulltext_only, innodb_optimize_fulltext_only, | ||
| 25751 | PLUGIN_VAR_NOCMDARG, | ||
| 25752 | "Only optimize the Fulltext index of the table", | ||
| 25753 | nullptr, nullptr, false); | ||
| 25754 | |||
| 25755 | static MYSQL_SYSVAR_ULONG(read_io_threads, srv_n_read_io_threads, | ||
| 25756 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25757 | "Number of background read I/O threads in InnoDB.", | ||
| 25758 | nullptr, nullptr, 4, 1, 64, 0); | ||
| 25759 | |||
| 25760 | static MYSQL_SYSVAR_ULONG(write_io_threads, srv_n_write_io_threads, | ||
| 25761 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25762 | "Number of background write I/O threads in InnoDB.", | ||
| 25763 | nullptr, nullptr, 4, 1, 64, 0); | ||
| 25764 | |||
| 25765 | static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery, | ||
| 25766 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25767 | "Helps to save your data in case the disk image of " | ||
| 25768 | "the database becomes corrupt.", | ||
| 25769 | nullptr, nullptr, 0, 0, 6, 0); | ||
| 25770 | |||
| 25771 | #ifdef UNIV_DEBUG | ||
| 25772 | static MYSQL_SYSVAR_ULONG(force_recovery_crash, srv_force_recovery_crash, | ||
| 25773 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25774 | "Kills the server during crash recovery.", nullptr, | ||
| 25775 | nullptr, 0, 0, 100, 0); | ||
| 25776 | #endif /* UNIV_DEBUG */ | ||
| 25777 | |||
| 25778 | static MYSQL_SYSVAR_ULONG(page_size, srv_page_size, | ||
| 25779 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY | | ||
| 25780 | PLUGIN_VAR_NOPERSIST, | ||
| 25781 | "Page size to use for all InnoDB tablespaces.", | ||
| 25782 | nullptr, nullptr, UNIV_PAGE_SIZE_DEF, | ||
| 25783 | UNIV_PAGE_SIZE_MIN, UNIV_PAGE_SIZE_MAX, 0); | ||
| 25784 | |||
| 25785 | static MYSQL_SYSVAR_ULONG( | ||
| 25786 | log_buffer_size, srv_log_buffer_size, PLUGIN_VAR_RQCMDARG, | ||
| 25787 | "The size of the buffer which InnoDB uses to write log to the log files" | ||
| 25788 | " on disk.", | ||
| 25789 | nullptr, innodb_log_buffer_size_update, INNODB_LOG_BUFFER_SIZE_DEFAULT, | ||
| 25790 | INNODB_LOG_BUFFER_SIZE_MIN, INNODB_LOG_BUFFER_SIZE_MAX, 1024); | ||
| 25791 | |||
| 25792 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 25793 | log_file_size, srv_log_file_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25794 | "Size of each log file before upgrading to 8.0.30. Deprecated.", nullptr, | ||
| 25795 | nullptr, 48 * 1024 * 1024L, 4 * 1024 * 1024L, ULLONG_MAX, 1024 * 1024L); | ||
| 25796 | |||
| 25797 | static MYSQL_SYSVAR_ULONG( | ||
| 25798 | log_files_in_group, srv_log_n_files, | ||
| 25799 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25800 | "Number of log files before upgrading to 8.0.30. Deprecated.", nullptr, | ||
| 25801 | nullptr, 2, 2, 100, 0); | ||
| 25802 | |||
| 25803 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 25804 | redo_log_capacity, srv_redo_log_capacity, | ||
| 25805 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_PERSIST_AS_READ_ONLY, | ||
| 25806 | "Limitation for total size of redo log files on disk (expressed in bytes).", | ||
| 25807 | nullptr, innodb_redo_log_capacity_update, 100 * 1024 * 1024, | ||
| 25808 | LOG_CAPACITY_MIN, LOG_CAPACITY_MAX, MB); | ||
| 25809 | |||
| 25810 | #ifdef UNIV_DEBUG_DEDICATED | ||
| 25811 | static MYSQL_SYSVAR_ULONG( | ||
| 25812 | debug_sys_mem_size, srv_debug_system_mem_size, | ||
| 25813 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25814 | "System memory size. It's for debuging dedicated server.", NULL, NULL, | ||
| 25815 | 48 * 1024 * 1024L, 4 * 1024 * 1024L, ULLONG_MAX, 1024 * 1024L); | ||
| 25816 | #endif /* UNIV_DEBUG_DEDICATED */ | ||
| 25817 | |||
| 25818 | static MYSQL_SYSVAR_ULONG(log_write_ahead_size, srv_log_write_ahead_size, | ||
| 25819 | PLUGIN_VAR_RQCMDARG, | ||
| 25820 | "Log write ahead unit size to avoid read-on-write," | ||
| 25821 | " it should match the OS cache block IO size.", | ||
| 25822 | nullptr, innodb_log_write_ahead_size_update, | ||
| 25823 | INNODB_LOG_WRITE_AHEAD_SIZE_DEFAULT, | ||
| 25824 | INNODB_LOG_WRITE_AHEAD_SIZE_MIN, | ||
| 25825 | INNODB_LOG_WRITE_AHEAD_SIZE_MAX, | ||
| 25826 | OS_FILE_LOG_BLOCK_SIZE); | ||
| 25827 | |||
| 25828 | static MYSQL_SYSVAR_BOOL( | ||
| 25829 | log_writer_threads, srv_log_writer_threads, PLUGIN_VAR_RQCMDARG, | ||
| 25830 | "Whether the log writer threads should be activated (ON), or write/flush " | ||
| 25831 | "of the redo log should be done by each thread individually (OFF).", | ||
| 25832 | nullptr, innodb_log_writer_threads_update, true); | ||
| 25833 | |||
| 25834 | static MYSQL_SYSVAR_UINT( | ||
| 25835 | log_spin_cpu_abs_lwm, srv_log_spin_cpu_abs_lwm, PLUGIN_VAR_RQCMDARG, | ||
| 25836 | "Minimum value of cpu time for which spin-delay is used." | ||
| 25837 | " Expressed in percentage of single cpu core.", | ||
| 25838 | nullptr, nullptr, INNODB_LOG_SPIN_CPU_ABS_LWM_DEFAULT, 0, UINT_MAX, 0); | ||
| 25839 | |||
| 25840 | static MYSQL_SYSVAR_UINT( | ||
| 25841 | log_spin_cpu_pct_hwm, srv_log_spin_cpu_pct_hwm, PLUGIN_VAR_RQCMDARG, | ||
| 25842 | "Maximum value of cpu time for which spin-delay is used." | ||
| 25843 | " Expressed in percentage of all cpu cores.", | ||
| 25844 | nullptr, nullptr, INNODB_LOG_SPIN_CPU_PCT_HWM_DEFAULT, 0, 100, 0); | ||
| 25845 | |||
| 25846 | static MYSQL_SYSVAR_ULONG( | ||
| 25847 | log_wait_for_flush_spin_hwm, srv_log_wait_for_flush_spin_hwm, | ||
| 25848 | PLUGIN_VAR_RQCMDARG, | ||
| 25849 | "Maximum value of average log flush time for which spin-delay is used." | ||
| 25850 | " When flushing takes longer, user threads no longer spin when waiting for" | ||
| 25851 | "flushed redo. Expressed in microseconds.", | ||
| 25852 | nullptr, nullptr, INNODB_LOG_WAIT_FOR_FLUSH_SPIN_HWM_DEFAULT, 0, ULONG_MAX, | ||
| 25853 | 0); | ||
| 25854 | |||
| 25855 | #ifdef ENABLE_EXPERIMENT_SYSVARS | ||
| 25856 | |||
| 25857 | static MYSQL_SYSVAR_ULONG( | ||
| 25858 | log_write_events, srv_log_write_events, | ||
| 25859 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25860 | "Number of events used for notifications about log write.", NULL, NULL, | ||
| 25861 | INNODB_LOG_EVENTS_DEFAULT, INNODB_LOG_EVENTS_MIN, INNODB_LOG_EVENTS_MAX, 0); | ||
| 25862 | |||
| 25863 | static MYSQL_SYSVAR_ULONG( | ||
| 25864 | log_flush_events, srv_log_flush_events, | ||
| 25865 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25866 | "Number of events used for notifications about log flush.", NULL, NULL, | ||
| 25867 | INNODB_LOG_EVENTS_DEFAULT, INNODB_LOG_EVENTS_MIN, INNODB_LOG_EVENTS_MAX, 0); | ||
| 25868 | |||
| 25869 | static MYSQL_SYSVAR_ULONG( | ||
| 25870 | log_recent_written_size, srv_log_recent_written_size, | ||
| 25871 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25872 | "Size of a small buffer, which allows concurrent writes to log buffer.", | ||
| 25873 | NULL, NULL, INNODB_LOG_RECENT_WRITTEN_SIZE_DEFAULT, | ||
| 25874 | INNODB_LOG_RECENT_WRITTEN_SIZE_MIN, INNODB_LOG_RECENT_WRITTEN_SIZE_MAX, 0); | ||
| 25875 | |||
| 25876 | static MYSQL_SYSVAR_ULONG( | ||
| 25877 | log_recent_closed_size, srv_log_recent_closed_size, | ||
| 25878 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25879 | "Size of a small buffer, which allows to break requirement for total order" | ||
| 25880 | " of dirty pages, when they are added to flush lists.", | ||
| 25881 | NULL, NULL, INNODB_LOG_RECENT_CLOSED_SIZE_DEFAULT, | ||
| 25882 | INNODB_LOG_RECENT_CLOSED_SIZE_MIN, INNODB_LOG_RECENT_CLOSED_SIZE_MAX, 0); | ||
| 25883 | |||
| 25884 | static MYSQL_SYSVAR_ULONG( | ||
| 25885 | log_wait_for_write_spin_delay, srv_log_wait_for_write_spin_delay, | ||
| 25886 | PLUGIN_VAR_RQCMDARG, | ||
| 25887 | "Number of spin iterations, when spinning and waiting for log buffer" | ||
| 25888 | " written up to given LSN, before we fallback to loop with sleeps." | ||
| 25889 | " This is not used when user thread has to wait for log flushed to disk.", | ||
| 25890 | NULL, NULL, INNODB_LOG_WAIT_FOR_WRITE_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25891 | |||
| 25892 | extern ulong srv_log_wait_for_write_timeout; | ||
| 25893 | static MYSQL_SYSVAR_ULONG( | ||
| 25894 | log_wait_for_write_timeout, srv_log_wait_for_write_timeout, | ||
| 25895 | PLUGIN_VAR_RQCMDARG, | ||
| 25896 | "Timeout used when waiting for redo write (microseconds).", NULL, NULL, | ||
| 25897 | INNODB_LOG_WAIT_FOR_WRITE_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25898 | |||
| 25899 | static MYSQL_SYSVAR_ULONG( | ||
| 25900 | log_wait_for_flush_spin_delay, srv_log_wait_for_flush_spin_delay, | ||
| 25901 | PLUGIN_VAR_RQCMDARG, | ||
| 25902 | "Number of spin iterations, when spinning and waiting for log flushed.", | ||
| 25903 | NULL, NULL, INNODB_LOG_WAIT_FOR_FLUSH_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25904 | |||
| 25905 | extern ulong srv_log_wait_for_flush_timeout; | ||
| 25906 | static MYSQL_SYSVAR_ULONG( | ||
| 25907 | log_wait_for_flush_timeout, srv_log_wait_for_flush_timeout, | ||
| 25908 | PLUGIN_VAR_RQCMDARG, | ||
| 25909 | "Timeout used when waiting for redo flush (microseconds).", NULL, NULL, | ||
| 25910 | INNODB_LOG_WAIT_FOR_FLUSH_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25911 | |||
| 25912 | static MYSQL_SYSVAR_ULONG( | ||
| 25913 | log_write_max_size, srv_log_write_max_size, PLUGIN_VAR_RQCMDARG, | ||
| 25914 | "Size available for next write, which satisfies log_writer thread" | ||
| 25915 | " when it follows links in recent written buffer.", | ||
| 25916 | NULL, NULL, INNODB_LOG_WRITE_MAX_SIZE_DEFAULT, 0, ULONG_MAX, | ||
| 25917 | OS_FILE_LOG_BLOCK_SIZE); | ||
| 25918 | |||
| 25919 | static MYSQL_SYSVAR_ULONG( | ||
| 25920 | log_writer_spin_delay, srv_log_writer_spin_delay, PLUGIN_VAR_RQCMDARG, | ||
| 25921 | "Number of spin iterations, for which log writer thread is waiting" | ||
| 25922 | " for new data to write without sleeping.", | ||
| 25923 | NULL, NULL, INNODB_LOG_WRITER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25924 | |||
| 25925 | extern ulong srv_log_writer_timeout; | ||
| 25926 | static MYSQL_SYSVAR_ULONG( | ||
| 25927 | log_writer_timeout, srv_log_writer_timeout, PLUGIN_VAR_RQCMDARG, | ||
| 25928 | "Initial timeout used to wait on event in log writer thread (microseconds)", | ||
| 25929 | NULL, NULL, INNODB_LOG_WRITER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25930 | |||
| 25931 | extern ulong srv_log_checkpoint_every; | ||
| 25932 | static MYSQL_SYSVAR_ULONG( | ||
| 25933 | log_checkpoint_every, srv_log_checkpoint_every, PLUGIN_VAR_RQCMDARG, | ||
| 25934 | "Checkpoints are executed at least every that many milliseconds.", NULL, | ||
| 25935 | NULL, INNODB_LOG_CHECKPOINT_EVERY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25936 | |||
| 25937 | static MYSQL_SYSVAR_ULONG( | ||
| 25938 | log_flusher_spin_delay, srv_log_flusher_spin_delay, PLUGIN_VAR_RQCMDARG, | ||
| 25939 | "Number of spin iterations, for which log flusher thread is waiting" | ||
| 25940 | " for new data to flush, without sleeping.", | ||
| 25941 | NULL, NULL, INNODB_LOG_FLUSHER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25942 | |||
| 25943 | extern ulong srv_log_flusher_timeout; | ||
| 25944 | static MYSQL_SYSVAR_ULONG(log_flusher_timeout, srv_log_flusher_timeout, | ||
| 25945 | PLUGIN_VAR_RQCMDARG, | ||
| 25946 | "Initial timeout used to wait on event in log " | ||
| 25947 | "flusher thread (microseconds)", | ||
| 25948 | NULL, NULL, INNODB_LOG_FLUSHER_TIMEOUT_DEFAULT, 0, | ||
| 25949 | ULONG_MAX, 0); | ||
| 25950 | |||
| 25951 | static MYSQL_SYSVAR_ULONG( | ||
| 25952 | log_write_notifier_spin_delay, srv_log_write_notifier_spin_delay, | ||
| 25953 | PLUGIN_VAR_RQCMDARG, | ||
| 25954 | "Number of spin iterations, for which log write notifier thread is waiting" | ||
| 25955 | " for advanced write_lsn, without sleeping.", | ||
| 25956 | NULL, NULL, INNODB_LOG_WRITE_NOTIFIER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25957 | |||
| 25958 | extern ulong srv_log_write_notifier_timeout; | ||
| 25959 | static MYSQL_SYSVAR_ULONG( | ||
| 25960 | log_write_notifier_timeout, srv_log_write_notifier_timeout, | ||
| 25961 | PLUGIN_VAR_RQCMDARG, | ||
| 25962 | "Initial timeout used to wait on event in log write notifier thread" | ||
| 25963 | " (microseconds)", | ||
| 25964 | NULL, NULL, INNODB_LOG_WRITE_NOTIFIER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25965 | |||
| 25966 | static MYSQL_SYSVAR_ULONG( | ||
| 25967 | log_flush_notifier_spin_delay, srv_log_flush_notifier_spin_delay, | ||
| 25968 | PLUGIN_VAR_RQCMDARG, | ||
| 25969 | "Number of spin iterations, for which log flush notifier thread is waiting" | ||
| 25970 | " for advanced flushed_to_disk_lsn, without sleeping.", | ||
| 25971 | NULL, NULL, INNODB_LOG_FLUSH_NOTIFIER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25972 | |||
| 25973 | extern ulong srv_log_flush_notifier_timeout; | ||
| 25974 | static MYSQL_SYSVAR_ULONG( | ||
| 25975 | log_flush_notifier_timeout, srv_log_flush_notifier_timeout, | ||
| 25976 | PLUGIN_VAR_RQCMDARG, | ||
| 25977 | "Initial timeout used to wait on event in log flush notifier thread" | ||
| 25978 | " (microseconds)", | ||
| 25979 | NULL, NULL, INNODB_LOG_FLUSH_NOTIFIER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 25980 | |||
| 25981 | #endif /* ENABLE_EXPERIMENT_SYSVARS */ | ||
| 25982 | |||
| 25983 | static MYSQL_SYSVAR_UINT( | ||
| 25984 | old_blocks_pct, innobase_old_blocks_pct, PLUGIN_VAR_RQCMDARG, | ||
| 25985 | "Percentage of the buffer pool to reserve for 'old' blocks.", nullptr, | ||
| 25986 | innodb_old_blocks_pct_update, 100 * 3 / 8, 5, 95, 0); | ||
| 25987 | |||
| 25988 | extern uint buf_LRU_old_threshold; | ||
| 25989 | static MYSQL_SYSVAR_UINT( | ||
| 25990 | old_blocks_time, buf_LRU_old_threshold, PLUGIN_VAR_RQCMDARG, | ||
| 25991 | "Move blocks to the 'new' end of the buffer pool if the first access" | ||
| 25992 | " was at least this many milliseconds ago." | ||
| 25993 | " The timeout is disabled if 0.", | ||
| 25994 | nullptr, nullptr, 1000, 0, UINT_MAX32, 0); | ||
| 25995 | |||
| 25996 | static MYSQL_SYSVAR_LONG( | ||
| 25997 | open_files, innobase_open_files, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 25998 | "How many files at the maximum InnoDB keeps open at the same time.", | ||
| 25999 | nullptr, nullptr, 0L, 0L, LONG_MAX, 0); | ||
| 26000 | |||
| 26001 | static MYSQL_SYSVAR_ULONG( | ||
| 26002 | sync_spin_loops, srv_n_spin_wait_rounds, PLUGIN_VAR_RQCMDARG, | ||
| 26003 | "Count of spin-loop rounds in InnoDB mutexes (30 by default)", nullptr, | ||
| 26004 | nullptr, 30L, 0L, ~0UL, 0); | ||
| 26005 | |||
| 26006 | static MYSQL_SYSVAR_ULONG( | ||
| 26007 | spin_wait_delay, srv_spin_wait_delay, PLUGIN_VAR_OPCMDARG, | ||
| 26008 | "Maximum delay between polling for a spin lock (6 by default)", nullptr, | ||
| 26009 | nullptr, 6L, 0L, 1000, 0); | ||
| 26010 | |||
| 26011 | static MYSQL_SYSVAR_ULONG(spin_wait_pause_multiplier, | ||
| 26012 | ut::spin_wait_pause_multiplier, PLUGIN_VAR_RQCMDARG, | ||
| 26013 | "Controls how many times in a row to use a PAUSE " | ||
| 26014 | "instruction to achieve one unit of delay in a spin " | ||
| 26015 | "lock (see @@innodb_spin_wait_delay), defaults to 50", | ||
| 26016 | nullptr, nullptr, 50, 0, 100, 0); | ||
| 26017 | |||
| 26018 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 26019 | fsync_threshold, os_fsync_threshold, PLUGIN_VAR_RQCMDARG, | ||
| 26020 | "The value of this variable determines how often InnoDB calls fsync when " | ||
| 26021 | "creating a new file. Default is zero which would make InnoDB flush the " | ||
| 26022 | "entire file at once before closing it.", | ||
| 26023 | nullptr, nullptr, 0, 0, ~0ULL, UNIV_PAGE_SIZE); | ||
| 26024 | |||
| 26025 | static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency, | ||
| 26026 | PLUGIN_VAR_RQCMDARG, | ||
| 26027 | "Helps in performance tuning in heavily concurrent " | ||
| 26028 | "environments. Sets the maximum number of threads " | ||
| 26029 | "allowed inside InnoDB. Value 0 will disable the " | ||
| 26030 | "thread throttling.", | ||
| 26031 | nullptr, innodb_thread_concurrency_update, 0, 0, 1000, | ||
| 26032 | 0); | ||
| 26033 | |||
| 26034 | static MYSQL_SYSVAR_ULONG( | ||
| 26035 | adaptive_max_sleep_delay, srv_adaptive_max_sleep_delay, PLUGIN_VAR_RQCMDARG, | ||
| 26036 | "The upper limit of the sleep delay in usec. Value of 0 disables it.", | ||
| 26037 | nullptr, nullptr, 150000, /* Default setting */ | ||
| 26038 | 0, /* Minimum value */ | ||
| 26039 | 1000000, 0); /* Maximum value */ | ||
| 26040 | |||
| 26041 | static MYSQL_SYSVAR_ULONG( | ||
| 26042 | thread_sleep_delay, srv_thread_sleep_delay, PLUGIN_VAR_RQCMDARG, | ||
| 26043 | "Time of innodb thread sleeping before joining InnoDB queue (usec)." | ||
| 26044 | " Value 0 disable a sleep", | ||
| 26045 | nullptr, nullptr, 10000L, 0L, 1000000L, 0); | ||
| 26046 | |||
| 26047 | static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path, | ||
| 26048 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | | ||
| 26049 | PLUGIN_VAR_NOPERSIST, | ||
| 26050 | "Path to individual files and their sizes.", nullptr, | ||
| 26051 | nullptr, (char *)"ibdata1:12M:autoextend"); | ||
| 26052 | |||
| 26053 | static MYSQL_SYSVAR_STR(temp_data_file_path, innobase_temp_data_file_path, | ||
| 26054 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | | ||
| 26055 | PLUGIN_VAR_NOPERSIST, | ||
| 26056 | "Path to files and their sizes making temp-tablespace.", | ||
| 26057 | nullptr, nullptr, (char *)"ibtmp1:12M:autoextend"); | ||
| 26058 | |||
| 26059 | static MYSQL_SYSVAR_BOOL( | ||
| 26060 | temp_tablespace_encrypt, srv_tmp_tablespace_encrypt, PLUGIN_VAR_OPCMDARG, | ||
| 26061 | "Enable or disable encryption of temporary tablespace.", nullptr, | ||
| 26062 | innodb_temp_tablespace_encryption_update, false); | ||
| 26063 | |||
| 26064 | static MYSQL_SYSVAR_ENUM( | ||
| 26065 | sys_tablespace_encrypt, srv_sys_tablespace_encrypt, | ||
| 26066 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 26067 | "Enable this option at bootstrap to encrypt system tablespace." | ||
| 26068 | "Set it to RE_ENCRYPTING_TO_KEYRING to allow re-encryption to KEYRING.", | ||
| 26069 | innodb_sys_tablespace_encyption_validate, nullptr, | ||
| 26070 | SYS_TABLESPACE_ENCRYPT_OFF, &sys_tablespace_encrypt_typelib); | ||
| 26071 | |||
| 26072 | static MYSQL_SYSVAR_STR( | ||
| 26073 | undo_directory, srv_undo_dir, | ||
| 26074 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 26075 | "Directory where undo tablespace files live, this path can be absolute.", | ||
| 26076 | nullptr, nullptr, nullptr); | ||
| 26077 | |||
| 26078 | static MYSQL_SYSVAR_STR( | ||
| 26079 | temp_tablespaces_dir, ibt::srv_temp_dir, | ||
| 26080 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 26081 | "Directory where temp tablespace files live, this path can be absolute.", | ||
| 26082 | nullptr, nullptr, nullptr); | ||
| 26083 | |||
| 26084 | static MYSQL_SYSVAR_ULONG(undo_tablespaces, srv_undo_tablespaces, | ||
| 26085 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 26086 | "Number of undo tablespaces to use. (deprecated)", | ||
| 26087 | nullptr, innodb_undo_tablespaces_update, | ||
| 26088 | FSP_IMPLICIT_UNDO_TABLESPACES, /* Default seting */ | ||
| 26089 | FSP_MIN_UNDO_TABLESPACES, /* Minimum value */ | ||
| 26090 | FSP_MAX_UNDO_TABLESPACES, 0); /* Maximum value */ | ||
| 26091 | |||
| 26092 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 26093 | max_undo_log_size, srv_max_undo_tablespace_size, PLUGIN_VAR_OPCMDARG, | ||
| 26094 | "Maximum size of an UNDO tablespace in MB (If an UNDO tablespace grows" | ||
| 26095 | " beyond this size it will be truncated in due course). ", | ||
| 26096 | nullptr, nullptr, 1024 * 1024 * 1024L, 10 * 1024 * 1024L, ~0ULL, 0); | ||
| 26097 | |||
| 26098 | static MYSQL_SYSVAR_ULONG( | ||
| 26099 | purge_rseg_truncate_frequency, srv_purge_rseg_truncate_frequency, | ||
| 26100 | PLUGIN_VAR_OPCMDARG, | ||
| 26101 | "Dictates rate at which UNDO records are purged. Value N means" | ||
| 26102 | " purge rollback segment(s) on every Nth iteration of purge invocation", | ||
| 26103 | nullptr, nullptr, 128, 1, 128, 0); | ||
| 26104 | |||
| 26105 | static MYSQL_SYSVAR_BOOL(undo_log_truncate, srv_undo_log_truncate, | ||
| 26106 | PLUGIN_VAR_OPCMDARG, | ||
| 26107 | "Enable or Disable Truncate of UNDO tablespace.", | ||
| 26108 | nullptr, nullptr, true); | ||
| 26109 | |||
| 26110 | /* This is the number of rollback segments per undo tablespace. | ||
| 26111 | This applies to the temporary tablespace, the system tablespace, | ||
| 26112 | and all undo tablespaces. */ | ||
| 26113 | static MYSQL_SYSVAR_ULONG( | ||
| 26114 | rollback_segments, srv_rollback_segments, PLUGIN_VAR_OPCMDARG, | ||
| 26115 | "Number of rollback segments per tablespace. This applies to the system" | ||
| 26116 | " tablespace, the temporary tablespace & any undo tablespace.", | ||
| 26117 | nullptr, innodb_rollback_segments_update, | ||
| 26118 | FSP_MAX_ROLLBACK_SEGMENTS, /* Default setting */ | ||
| 26119 | 1, /* Minimum value */ | ||
| 26120 | FSP_MAX_ROLLBACK_SEGMENTS, 0); /* Maximum value */ | ||
| 26121 | |||
| 26122 | static MYSQL_SYSVAR_BOOL(undo_log_encrypt, srv_undo_log_encrypt, | ||
| 26123 | PLUGIN_VAR_OPCMDARG, | ||
| 26124 | "Enable or disable Encrypt of UNDO tablespace.", | ||
| 26125 | validate_innodb_undo_log_encrypt, nullptr, false); | ||
| 26126 | |||
| 26127 | static MYSQL_SYSVAR_LONG( | ||
| 26128 | autoinc_lock_mode, innobase_autoinc_lock_mode, | ||
| 26129 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 26130 | "The AUTOINC lock modes supported by InnoDB:" | ||
| 26131 | " 0 => Old style AUTOINC locking (for backward compatibility);" | ||
| 26132 | " 1 => New style AUTOINC locking;" | ||
| 26133 | " 2 => No AUTOINC locking (unsafe for SBR)", | ||
| 26134 | nullptr, nullptr, AUTOINC_NO_LOCKING, /* Default setting */ | ||
| 26135 | AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */ | ||
| 26136 | AUTOINC_NO_LOCKING, 0); /* Maximum value */ | ||
| 26137 | |||
| 26138 | static MYSQL_SYSVAR_STR(version, innodb_version_str, | ||
| 26139 | PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY | | ||
| 26140 | PLUGIN_VAR_NOPERSIST, | ||
| 26141 | "InnoDB version", nullptr, nullptr, INNODB_VERSION_STR); | ||
| 26142 | |||
| 26143 | static MYSQL_SYSVAR_BOOL(use_native_aio, srv_use_native_aio, | ||
| 26144 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 26145 | "Use native AIO if supported on this platform.", | ||
| 26146 | nullptr, nullptr, true); | ||
| 26147 | |||
| 26148 | #ifdef HAVE_LIBNUMA | ||
| 26149 | static MYSQL_SYSVAR_BOOL( | ||
| 26150 | numa_interleave, srv_numa_interleave, | ||
| 26151 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 26152 | "Use NUMA interleave memory policy to allocate InnoDB buffer pool.", | ||
| 26153 | nullptr, nullptr, false); | ||
| 26154 | #endif /* HAVE_LIBNUMA */ | ||
| 26155 | |||
| 26156 | static MYSQL_SYSVAR_BOOL( | ||
| 26157 | api_enable_binlog, ib_binlog_enabled, | ||
| 26158 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 26159 | "Enable binlog for applications direct access InnoDB through InnoDB APIs", | ||
| 26160 | nullptr, nullptr, false); | ||
| 26161 | |||
| 26162 | static MYSQL_SYSVAR_BOOL( | ||
| 26163 | api_enable_mdl, ib_mdl_enabled, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 26164 | "Enable MDL for applications direct access InnoDB through InnoDB APIs", | ||
| 26165 | nullptr, nullptr, false); | ||
| 26166 | |||
| 26167 | static MYSQL_SYSVAR_BOOL( | ||
| 26168 | api_disable_rowlock, ib_disable_row_lock, | ||
| 26169 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 26170 | "Disable row lock when direct access InnoDB through InnoDB APIs", nullptr, | ||
| 26171 | nullptr, false); | ||
| 26172 | |||
| 26173 | static MYSQL_SYSVAR_ULONG(api_trx_level, ib_trx_level_setting, | ||
| 26174 | PLUGIN_VAR_OPCMDARG, | ||
| 26175 | "InnoDB API transaction isolation level", nullptr, | ||
| 26176 | nullptr, 0, /* Default setting */ | ||
| 26177 | 0, /* Minimum value */ | ||
| 26178 | 3, 0); /* Maximum value */ | ||
| 26179 | |||
| 26180 | static MYSQL_SYSVAR_ULONG(api_bk_commit_interval, ib_bk_commit_interval, | ||
| 26181 | PLUGIN_VAR_OPCMDARG, | ||
| 26182 | "Background commit interval in seconds", nullptr, | ||
| 26183 | nullptr, 5, /* Default setting */ | ||
| 26184 | 1, /* Minimum value */ | ||
| 26185 | 1024 * 1024 * 1024, 0); /* Maximum value */ | ||
| 26186 | |||
| 26187 | static MYSQL_SYSVAR_ENUM(change_buffering, innodb_change_buffering, | ||
| 26188 | PLUGIN_VAR_RQCMDARG, | ||
| 26189 | "Buffer changes to reduce random access:" | ||
| 26190 | " OFF, ON, inserting, deleting, changing, or purging.", | ||
| 26191 | nullptr, nullptr, IBUF_USE_ALL, | ||
| 26192 | &innodb_change_buffering_typelib); | ||
| 26193 | |||
| 26194 | static MYSQL_SYSVAR_UINT( | ||
| 26195 | change_buffer_max_size, srv_change_buffer_max_size, PLUGIN_VAR_RQCMDARG, | ||
| 26196 | "Maximum on-disk size of change buffer in terms of percentage" | ||
| 26197 | " of the buffer pool.", | ||
| 26198 | nullptr, innodb_change_buffer_max_size_update, CHANGE_BUFFER_DEFAULT_SIZE, | ||
| 26199 | 0, 50, 0); | ||
| 26200 | |||
| 26201 | static MYSQL_SYSVAR_ENUM( | ||
| 26202 | stats_method, srv_innodb_stats_method, PLUGIN_VAR_RQCMDARG, | ||
| 26203 | "Specifies how InnoDB index statistics collection code should" | ||
| 26204 | " treat NULLs. Possible values are NULLS_EQUAL (default)," | ||
| 26205 | " NULLS_UNEQUAL and NULLS_IGNORED", | ||
| 26206 | nullptr, nullptr, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib); | ||
| 26207 | |||
| 26208 | #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG | ||
| 26209 | static MYSQL_SYSVAR_UINT( | ||
| 26210 | change_buffering_debug, ibuf_debug, PLUGIN_VAR_RQCMDARG, | ||
| 26211 | "Debug flags for InnoDB change buffering (0=none, 2=crash at merge)", | ||
| 26212 | nullptr, nullptr, 0, 0, 2, 0); | ||
| 26213 | |||
| 26214 | static MYSQL_SYSVAR_BOOL(disable_background_merge, | ||
| 26215 | srv_ibuf_disable_background_merge, | ||
| 26216 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_RQCMDARG, | ||
| 26217 | "Disable change buffering merges by the master thread", | ||
| 26218 | nullptr, nullptr, false); | ||
| 26219 | |||
| 26220 | static MYSQL_SYSVAR_ENUM( | ||
| 26221 | compress_debug, srv_debug_compress, PLUGIN_VAR_RQCMDARG, | ||
| 26222 | "Compress all tables, without specifying the COMPRESS table attribute", | ||
| 26223 | nullptr, nullptr, Compression::NONE, &innodb_debug_compress_typelib); | ||
| 26224 | #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ | ||
| 26225 | |||
| 26226 | #ifdef WITH_WSREP | ||
| 26227 | /* if rsync is being done on live/active node then it is important | ||
| 26228 | that innodb io write threads are not flushing/writing. | ||
| 26229 | FLUSH TABLE with READ LOCK will block external action but internal | ||
| 26230 | action or if the thread is actively writing then all such action | ||
| 26231 | needs to be avoided. rsync is like taking a snapshot at given | ||
| 26232 | point in time. If thread-1/2 are altering file-1/2 from innodb | ||
| 26233 | and both action are needed for complete data-directory to make sense | ||
| 26234 | then this sequence could break the rsync backed up copy. | ||
| 26235 | thread-1 write complete -> rsync -> thread-2 write complete */ | ||
| 26236 | |||
| 26237 | /* An "update" method for innobase_disallow_writes variable. */ | ||
| 26238 | 3 | static void innobase_disallow_writes_update( | |
| 26239 | THD *thd, // in: thread handle <] | ||
| 26240 | SYS_VAR *var, // in: pointer to | ||
| 26241 | // system variable */ | ||
| 26242 | void *var_ptr, // where the | ||
| 26243 | // formal string goes */ | ||
| 26244 | const void *save) { // in: immediate result | ||
| 26245 | // from check function | ||
| 26246 | 6 | ib::warn() << "innodb_disallow_writes has been deprecated and will be" | |
| 26247 | " removed in future release. Consider using read_only" | ||
| 26248 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | " instead."; |
| 26249 | |||
| 26250 | 3 | *(bool *)var_ptr = *(bool *)save; | |
| 26251 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | ut_a(srv_allow_writes_event); |
| 26252 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (*(bool *)var_ptr) |
| 26253 | ✗ | os_event_reset(srv_allow_writes_event); | |
| 26254 | else | ||
| 26255 | 3 | os_event_set(srv_allow_writes_event); | |
| 26256 | 3 | } | |
| 26257 | |||
| 26258 | static MYSQL_SYSVAR_BOOL(disallow_writes, innobase_disallow_writes, | ||
| 26259 | PLUGIN_VAR_NOCMDOPT, | ||
| 26260 | "Tell InnoDB to stop any writes to disk (deprecated)", | ||
| 26261 | NULL, innobase_disallow_writes_update, false); | ||
| 26262 | #endif /* WITH_WSREP */ | ||
| 26263 | |||
| 26264 | static MYSQL_SYSVAR_BOOL( | ||
| 26265 | random_read_ahead, srv_random_read_ahead, PLUGIN_VAR_NOCMDARG, | ||
| 26266 | "Whether to use read ahead for random access within an extent.", nullptr, | ||
| 26267 | nullptr, false); | ||
| 26268 | |||
| 26269 | static MYSQL_SYSVAR_ULONG( | ||
| 26270 | read_ahead_threshold, srv_read_ahead_threshold, PLUGIN_VAR_RQCMDARG, | ||
| 26271 | "Number of pages that must be accessed sequentially for InnoDB to" | ||
| 26272 | " trigger a readahead.", | ||
| 26273 | nullptr, nullptr, 56, 0, 64, 0); | ||
| 26274 | |||
| 26275 | static MYSQL_SYSVAR_STR(monitor_enable, innobase_enable_monitor_counter, | ||
| 26276 | PLUGIN_VAR_RQCMDARG, "Turn on a monitor counter", | ||
| 26277 | innodb_monitor_validate, innodb_enable_monitor_update, | ||
| 26278 | nullptr); | ||
| 26279 | |||
| 26280 | static MYSQL_SYSVAR_STR(monitor_disable, innobase_disable_monitor_counter, | ||
| 26281 | PLUGIN_VAR_RQCMDARG, "Turn off a monitor counter", | ||
| 26282 | innodb_monitor_validate, innodb_disable_monitor_update, | ||
| 26283 | nullptr); | ||
| 26284 | |||
| 26285 | static MYSQL_SYSVAR_STR(monitor_reset, innobase_reset_monitor_counter, | ||
| 26286 | PLUGIN_VAR_RQCMDARG, "Reset a monitor counter", | ||
| 26287 | innodb_monitor_validate, innodb_reset_monitor_update, | ||
| 26288 | nullptr); | ||
| 26289 | |||
| 26290 | static MYSQL_SYSVAR_STR(monitor_reset_all, innobase_reset_all_monitor_counter, | ||
| 26291 | PLUGIN_VAR_RQCMDARG, | ||
| 26292 | "Reset all values for a monitor counter", | ||
| 26293 | innodb_monitor_validate, | ||
| 26294 | innodb_reset_all_monitor_update, nullptr); | ||
| 26295 | |||
| 26296 | static MYSQL_SYSVAR_BOOL(status_output, srv_print_innodb_monitor, | ||
| 26297 | PLUGIN_VAR_OPCMDARG, | ||
| 26298 | "Enable InnoDB monitor output to the error log.", | ||
| 26299 | nullptr, nullptr, false); | ||
| 26300 | |||
| 26301 | static MYSQL_SYSVAR_BOOL(status_output_locks, srv_print_innodb_lock_monitor, | ||
| 26302 | PLUGIN_VAR_OPCMDARG, | ||
| 26303 | "Enable InnoDB lock monitor output to the error log." | ||
| 26304 | " Requires innodb_status_output=ON.", | ||
| 26305 | nullptr, nullptr, false); | ||
| 26306 | |||
| 26307 | static MYSQL_SYSVAR_BOOL( | ||
| 26308 | print_all_deadlocks, srv_print_all_deadlocks, PLUGIN_VAR_OPCMDARG, | ||
| 26309 | "Print all deadlocks to MySQL error log (off by default)", nullptr, nullptr, | ||
| 26310 | false); | ||
| 26311 | |||
| 26312 | static MYSQL_SYSVAR_BOOL( | ||
| 26313 | print_lock_wait_timeout_info, srv_print_lock_wait_timeout_info, | ||
| 26314 | PLUGIN_VAR_OPCMDARG, | ||
| 26315 | "Print lock wait timeout info to MySQL error log (off by default)", nullptr, | ||
| 26316 | nullptr, false); | ||
| 26317 | |||
| 26318 | static MYSQL_SYSVAR_ULONG( | ||
| 26319 | compression_failure_threshold_pct, zip_failure_threshold_pct, | ||
| 26320 | PLUGIN_VAR_OPCMDARG, | ||
| 26321 | "If the compression failure rate of a table is greater than this number" | ||
| 26322 | " more padding is added to the pages to reduce the failures. A value of" | ||
| 26323 | " zero implies no padding", | ||
| 26324 | nullptr, nullptr, 5, 0, 100, 0); | ||
| 26325 | |||
| 26326 | static MYSQL_SYSVAR_ULONG( | ||
| 26327 | compression_pad_pct_max, zip_pad_max, PLUGIN_VAR_OPCMDARG, | ||
| 26328 | "Percentage of empty space on a data page that can be reserved" | ||
| 26329 | " to make the page compressible.", | ||
| 26330 | nullptr, nullptr, 50, 0, 75, 0); | ||
| 26331 | |||
| 26332 | static MYSQL_SYSVAR_BOOL(read_only, srv_read_only_mode, | ||
| 26333 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY | | ||
| 26334 | PLUGIN_VAR_NOPERSIST, | ||
| 26335 | "Start InnoDB in read only mode (off by default)", | ||
| 26336 | nullptr, nullptr, false); | ||
| 26337 | |||
| 26338 | static MYSQL_SYSVAR_BOOL( | ||
| 26339 | cmp_per_index_enabled, srv_cmp_per_index_enabled, PLUGIN_VAR_OPCMDARG, | ||
| 26340 | "Enable INFORMATION_SCHEMA.innodb_cmp_per_index," | ||
| 26341 | " may have negative impact on performance (off by default)", | ||
| 26342 | nullptr, innodb_cmp_per_index_update, false); | ||
| 26343 | |||
| 26344 | static MYSQL_SYSVAR_ENUM( | ||
| 26345 | default_row_format, innodb_default_row_format, PLUGIN_VAR_RQCMDARG, | ||
| 26346 | "The default ROW FORMAT for all innodb tables created without explicit" | ||
| 26347 | " ROW_FORMAT. Possible values are REDUNDANT, COMPACT, and DYNAMIC." | ||
| 26348 | " The ROW_FORMAT value COMPRESSED is not allowed", | ||
| 26349 | nullptr, nullptr, DEFAULT_ROW_FORMAT_DYNAMIC, | ||
| 26350 | &innodb_default_row_format_typelib); | ||
| 26351 | |||
| 26352 | static MYSQL_SYSVAR_STR( | ||
| 26353 | redo_log_archive_dirs, meb::redo_log_archive_dirs, | ||
| 26354 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 26355 | "Limit the location of the redo log archive to the semicolon " | ||
| 26356 | "separated list of labeled directories", | ||
| 26357 | /*validate_func*/ meb::validate_redo_log_archive_dirs, | ||
| 26358 | /*update_func*/ nullptr, /*default*/ nullptr); | ||
| 26359 | |||
| 26360 | static MYSQL_SYSVAR_BOOL(redo_log_encrypt, srv_redo_log_encrypt, | ||
| 26361 | PLUGIN_VAR_OPCMDARG, | ||
| 26362 | "Enable or disable Encryption of REDO tablespace.", | ||
| 26363 | validate_innodb_redo_log_encrypt, nullptr, false); | ||
| 26364 | |||
| 26365 | static MYSQL_SYSVAR_BOOL( | ||
| 26366 | print_ddl_logs, srv_print_ddl_logs, PLUGIN_VAR_OPCMDARG, | ||
| 26367 | "Print all DDl logs to MySQL error log (off by default)", nullptr, nullptr, | ||
| 26368 | false); | ||
| 26369 | |||
| 26370 | #ifdef UNIV_DEBUG | ||
| 26371 | static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug, | ||
| 26372 | PLUGIN_VAR_RQCMDARG, | ||
| 26373 | "Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for " | ||
| 26374 | "trx_rsegf_undo_find_free()", | ||
| 26375 | nullptr, nullptr, 0, 0, 1024, 0); | ||
| 26376 | |||
| 26377 | static MYSQL_SYSVAR_UINT( | ||
| 26378 | limit_optimistic_insert_debug, btr_cur_limit_optimistic_insert_debug, | ||
| 26379 | PLUGIN_VAR_RQCMDARG, | ||
| 26380 | "Artificially limit the number of records per B-tree page (0=unlimited).", | ||
| 26381 | nullptr, nullptr, 0, 0, UINT_MAX32, 0); | ||
| 26382 | |||
| 26383 | static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug, | ||
| 26384 | srv_purge_view_update_only_debug, PLUGIN_VAR_NOCMDARG, | ||
| 26385 | "Pause actual purging any delete-marked records, but " | ||
| 26386 | "merely update the purge view." | ||
| 26387 | " It is to create artificially the situation the " | ||
| 26388 | "purge view have been updated" | ||
| 26389 | " but the each purges were not done yet.", | ||
| 26390 | nullptr, nullptr, false); | ||
| 26391 | // clang-format off | ||
| 26392 | static MYSQL_SYSVAR_ULONG( | ||
| 26393 | fil_make_page_dirty_debug, | ||
| 26394 | srv_fil_make_page_dirty_debug, PLUGIN_VAR_OPCMDARG, | ||
| 26395 | "Make the first page of the given tablespace dirty.", | ||
| 26396 | nullptr, innodb_make_page_dirty, UINT_MAX32, 0, UINT_MAX32, 0); | ||
| 26397 | // clang-format on | ||
| 26398 | |||
| 26399 | static MYSQL_SYSVAR_ULONG(saved_page_number_debug, srv_saved_page_number_debug, | ||
| 26400 | PLUGIN_VAR_OPCMDARG, "An InnoDB page number.", | ||
| 26401 | nullptr, innodb_save_page_no, 0, 0, UINT_MAX32, 0); | ||
| 26402 | |||
| 26403 | static MYSQL_SYSVAR_BOOL(page_cleaner_disabled_debug, | ||
| 26404 | innodb_page_cleaner_disabled_debug, | ||
| 26405 | PLUGIN_VAR_OPCMDARG, "Disable page cleaner", nullptr, | ||
| 26406 | buf_flush_page_cleaner_disabled_debug_update, false); | ||
| 26407 | |||
| 26408 | static MYSQL_SYSVAR_BOOL(dict_stats_disabled_debug, | ||
| 26409 | innodb_dict_stats_disabled_debug, PLUGIN_VAR_OPCMDARG, | ||
| 26410 | "Disable dict_stats thread", nullptr, | ||
| 26411 | dict_stats_disabled_debug_update, false); | ||
| 26412 | |||
| 26413 | static MYSQL_SYSVAR_BOOL(master_thread_disabled_debug, | ||
| 26414 | srv_master_thread_disabled_debug, PLUGIN_VAR_OPCMDARG, | ||
| 26415 | "Disable master thread", nullptr, | ||
| 26416 | srv_master_thread_disabled_debug_update, false); | ||
| 26417 | |||
| 26418 | static MYSQL_SYSVAR_BOOL(sync_debug, srv_sync_debug, | ||
| 26419 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 26420 | "Enable the sync debug checks", nullptr, nullptr, | ||
| 26421 | false); | ||
| 26422 | |||
| 26423 | static MYSQL_SYSVAR_BOOL(buffer_pool_debug, srv_buf_pool_debug, | ||
| 26424 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 26425 | "Enable buffer pool debug", nullptr, nullptr, false); | ||
| 26426 | |||
| 26427 | static MYSQL_SYSVAR_BOOL(ddl_log_crash_reset_debug, | ||
| 26428 | innodb_ddl_log_crash_reset_debug, PLUGIN_VAR_OPCMDARG, | ||
| 26429 | "Reset all crash injection counters to 1", nullptr, | ||
| 26430 | ddl_log_crash_reset, false); | ||
| 26431 | |||
| 26432 | #endif /* UNIV_DEBUG */ | ||
| 26433 | |||
| 26434 | static MYSQL_SYSVAR_STR(directories, srv_innodb_directories, | ||
| 26435 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | | ||
| 26436 | PLUGIN_VAR_NOPERSIST, | ||
| 26437 | "List of directories 'dir1;dir2;..;dirN' to scan for " | ||
| 26438 | "tablespace files. Default is to scan " | ||
| 26439 | "'innodb-data-home-dir;innodb-undo-directory;datadir'", | ||
| 26440 | nullptr, nullptr, nullptr); | ||
| 26441 | |||
| 26442 | #ifdef UNIV_DEBUG | ||
| 26443 | /** Use this variable innodb_interpreter to execute debug code within InnoDB. | ||
| 26444 | The output is stored in the innodb_interpreter_output variable. */ | ||
| 26445 | static MYSQL_THDVAR_STR(interpreter, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 26446 | "Invoke InnoDB test interpreter with commands" | ||
| 26447 | " to be executed.", | ||
| 26448 | ib_interpreter_check, ib_interpreter_update, "init"); | ||
| 26449 | |||
| 26450 | /** When testing commands are executed in the innodb_interpreter variable, the | ||
| 26451 | output is stored in this innodb_interpreter_output variable. */ | ||
| 26452 | static MYSQL_THDVAR_STR(interpreter_output, | ||
| 26453 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC | | ||
| 26454 | PLUGIN_VAR_NOPERSIST, | ||
| 26455 | "Output from InnoDB testing module (ut0test).", nullptr, | ||
| 26456 | nullptr, "The Default Value"); | ||
| 26457 | |||
| 26458 | 54 | char **thd_innodb_interpreter_output(THD *thd) { | |
| 26459 | return (MYSQL_SYSVAR_NAME(interpreter_output) | ||
| 26460 | 54 | .resolve(thd, MYSQL_SYSVAR_NAME(interpreter_output).offset)); | |
| 26461 | } | ||
| 26462 | |||
| 26463 | 54 | char **thd_innodb_interpreter(THD *thd) { | |
| 26464 | return MYSQL_SYSVAR_NAME(interpreter) | ||
| 26465 | 54 | .resolve(thd, MYSQL_SYSVAR_NAME(interpreter).offset); | |
| 26466 | } | ||
| 26467 | #endif /* UNIV_DEBUG */ | ||
| 26468 | |||
| 26469 | static const char *corrupt_table_action_names[] = {"assert", /* 0 */ | ||
| 26470 | "warn", /* 1 */ | ||
| 26471 | "salvage", /* 2 */ | ||
| 26472 | NullS}; | ||
| 26473 | |||
| 26474 | static TYPELIB corrupt_table_action_typelib = { | ||
| 26475 | array_elements(corrupt_table_action_names) - 1, | ||
| 26476 | "corrupt_table_action_typelib", corrupt_table_action_names, nullptr}; | ||
| 26477 | |||
| 26478 | static MYSQL_SYSVAR_ENUM( | ||
| 26479 | corrupt_table_action, srv_pass_corrupt_table, PLUGIN_VAR_RQCMDARG, | ||
| 26480 | "Warn corruptions of user tables as 'corrupt table' instead of not " | ||
| 26481 | "crashing itself, " | ||
| 26482 | "when used with file_per_table. " | ||
| 26483 | "All file io for the datafile after detected as corrupt are disabled, " | ||
| 26484 | "except for the deletion.", | ||
| 26485 | nullptr, nullptr, 0, &corrupt_table_action_typelib); | ||
| 26486 | |||
| 26487 | static MYSQL_SYSVAR_STR( | ||
| 26488 | parallel_doublewrite_path, srv_parallel_doublewrite_path_deprecated, | ||
| 26489 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 26490 | "Deprecated Percona-specific variable that was used to set path to the " | ||
| 26491 | "parallel doublewrite file and has no effect now. " | ||
| 26492 | "Use --innodb-doublewrite-dir instead.", | ||
| 26493 | nullptr, innodb_parallel_doublewrite_path_update, "xb_doublewrite"); | ||
| 26494 | |||
| 26495 | static MYSQL_SYSVAR_BOOL( | ||
| 26496 | parallel_dblwr_encrypt, srv_parallel_dblwr_encrypt_deprecated, | ||
| 26497 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 26498 | "Deprecated Percona-specific variable that was used to enable or " | ||
| 26499 | "disable encryption of parallel doublewrite buffer file and has no " | ||
| 26500 | "effect now.", | ||
| 26501 | nullptr, innodb_parallel_dblwr_encrypt_update, false); | ||
| 26502 | |||
| 26503 | static MYSQL_SYSVAR_UINT( | ||
| 26504 | compressed_columns_zip_level, srv_compressed_columns_zip_level, | ||
| 26505 | PLUGIN_VAR_RQCMDARG, | ||
| 26506 | "Compression level used for compressed columns. 0 is no compression" | ||
| 26507 | ", 1 is fastest and 9 is best compression. Default is 6.", | ||
| 26508 | nullptr, nullptr, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0); | ||
| 26509 | |||
| 26510 | static MYSQL_SYSVAR_ULONG( | ||
| 26511 | compressed_columns_threshold, srv_compressed_columns_threshold, | ||
| 26512 | PLUGIN_VAR_RQCMDARG, | ||
| 26513 | "Compress column data if its length exceeds this value. Default is 96", | ||
| 26514 | nullptr, nullptr, 96, 1, ~0UL, 0); | ||
| 26515 | |||
| 26516 | static MYSQL_SYSVAR_BOOL(encrypt_online_alter_logs, | ||
| 26517 | srv_encrypt_online_alter_logs, | ||
| 26518 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 26519 | "Encrypt online alter logs.", nullptr, nullptr, false); | ||
| 26520 | |||
| 26521 | static MYSQL_SYSVAR_UINT( | ||
| 26522 | encryption_threads, srv_n_fil_crypt_threads_requested, PLUGIN_VAR_RQCMDARG, | ||
| 26523 | "Number of threads performing background key rotation and " | ||
| 26524 | "scrubbing", | ||
| 26525 | innodb_encryption_threads_validate, innodb_encryption_threads_update, 0, 0, | ||
| 26526 | MAX_ENCRYPTION_THREADS, 0); | ||
| 26527 | |||
| 26528 | static MYSQL_SYSVAR_UINT(encryption_rotate_key_age, | ||
| 26529 | srv_fil_crypt_rotate_key_age, PLUGIN_VAR_RQCMDARG, | ||
| 26530 | "Key rotation - re-encrypt in background " | ||
| 26531 | "all pages that were encrypted with a key that " | ||
| 26532 | "many (or more) versions behind. Value 0 indicates " | ||
| 26533 | "that key rotation is disabled.", | ||
| 26534 | NULL, innodb_encryption_rotate_key_age_update, 1, 0, | ||
| 26535 | UINT_MAX32, 0); | ||
| 26536 | |||
| 26537 | static MYSQL_SYSVAR_UINT(encryption_rotation_iops, srv_n_fil_crypt_iops, | ||
| 26538 | PLUGIN_VAR_RQCMDARG, | ||
| 26539 | "Use this many iops for background key rotation", NULL, | ||
| 26540 | innodb_encryption_rotation_iops_update, | ||
| 26541 | srv_n_fil_crypt_iops, 0, UINT_MAX32, 0); | ||
| 26542 | |||
| 26543 | static SYS_VAR *innobase_system_variables[] = { | ||
| 26544 | MYSQL_SYSVAR(api_trx_level), | ||
| 26545 | MYSQL_SYSVAR(api_bk_commit_interval), | ||
| 26546 | MYSQL_SYSVAR(autoextend_increment), | ||
| 26547 | MYSQL_SYSVAR(dedicated_server), | ||
| 26548 | MYSQL_SYSVAR(buffer_pool_size), | ||
| 26549 | MYSQL_SYSVAR(buffer_pool_chunk_size), | ||
| 26550 | MYSQL_SYSVAR(buffer_pool_instances), | ||
| 26551 | MYSQL_SYSVAR(buffer_pool_filename), | ||
| 26552 | MYSQL_SYSVAR(buffer_pool_dump_now), | ||
| 26553 | MYSQL_SYSVAR(buffer_pool_dump_at_shutdown), | ||
| 26554 | MYSQL_SYSVAR(buffer_pool_in_core_file), | ||
| 26555 | MYSQL_SYSVAR(buffer_pool_dump_pct), | ||
| 26556 | #ifdef UNIV_DEBUG | ||
| 26557 | MYSQL_SYSVAR(buffer_pool_evict), | ||
| 26558 | #endif /* UNIV_DEBUG */ | ||
| 26559 | MYSQL_SYSVAR(buffer_pool_load_now), | ||
| 26560 | MYSQL_SYSVAR(buffer_pool_load_abort), | ||
| 26561 | MYSQL_SYSVAR(buffer_pool_load_at_startup), | ||
| 26562 | MYSQL_SYSVAR(lru_scan_depth), | ||
| 26563 | MYSQL_SYSVAR(flush_neighbors), | ||
| 26564 | MYSQL_SYSVAR(checksum_algorithm), | ||
| 26565 | MYSQL_SYSVAR(log_checksums), | ||
| 26566 | MYSQL_SYSVAR(commit_concurrency), | ||
| 26567 | MYSQL_SYSVAR(concurrency_tickets), | ||
| 26568 | MYSQL_SYSVAR(compression_level), | ||
| 26569 | MYSQL_SYSVAR(ddl_buffer_size), | ||
| 26570 | MYSQL_SYSVAR(ddl_threads), | ||
| 26571 | MYSQL_SYSVAR(data_file_path), | ||
| 26572 | MYSQL_SYSVAR(temp_data_file_path), | ||
| 26573 | MYSQL_SYSVAR(temp_tablespace_encrypt), | ||
| 26574 | MYSQL_SYSVAR(sys_tablespace_encrypt), | ||
| 26575 | MYSQL_SYSVAR(data_home_dir), | ||
| 26576 | MYSQL_SYSVAR(extend_and_initialize), | ||
| 26577 | MYSQL_SYSVAR(doublewrite), | ||
| 26578 | MYSQL_SYSVAR(doublewrite_dir), | ||
| 26579 | MYSQL_SYSVAR(doublewrite_batch_size), | ||
| 26580 | MYSQL_SYSVAR(doublewrite_files), | ||
| 26581 | MYSQL_SYSVAR(doublewrite_pages), | ||
| 26582 | MYSQL_SYSVAR(stats_include_delete_marked), | ||
| 26583 | MYSQL_SYSVAR(api_enable_binlog), | ||
| 26584 | MYSQL_SYSVAR(api_enable_mdl), | ||
| 26585 | MYSQL_SYSVAR(api_disable_rowlock), | ||
| 26586 | MYSQL_SYSVAR(fast_shutdown), | ||
| 26587 | MYSQL_SYSVAR(read_io_threads), | ||
| 26588 | MYSQL_SYSVAR(write_io_threads), | ||
| 26589 | MYSQL_SYSVAR(file_per_table), | ||
| 26590 | MYSQL_SYSVAR(flush_log_at_timeout), | ||
| 26591 | MYSQL_SYSVAR(flush_log_at_trx_commit), | ||
| 26592 | MYSQL_SYSVAR(flush_method), | ||
| 26593 | MYSQL_SYSVAR(force_recovery), | ||
| 26594 | #ifdef UNIV_DEBUG | ||
| 26595 | MYSQL_SYSVAR(force_recovery_crash), | ||
| 26596 | #endif /* UNIV_DEBUG */ | ||
| 26597 | MYSQL_SYSVAR(fill_factor), | ||
| 26598 | MYSQL_SYSVAR(ft_cache_size), | ||
| 26599 | MYSQL_SYSVAR(ft_total_cache_size), | ||
| 26600 | MYSQL_SYSVAR(ft_result_cache_limit), | ||
| 26601 | MYSQL_SYSVAR(ft_enable_stopword), | ||
| 26602 | MYSQL_SYSVAR(ft_max_token_size), | ||
| 26603 | MYSQL_SYSVAR(ft_min_token_size), | ||
| 26604 | MYSQL_SYSVAR(ft_num_word_optimize), | ||
| 26605 | MYSQL_SYSVAR(ft_sort_pll_degree), | ||
| 26606 | MYSQL_SYSVAR(force_load_corrupted), | ||
| 26607 | MYSQL_SYSVAR(lock_wait_timeout), | ||
| 26608 | MYSQL_SYSVAR(deadlock_detect), | ||
| 26609 | MYSQL_SYSVAR(page_size), | ||
| 26610 | MYSQL_SYSVAR(log_buffer_size), | ||
| 26611 | MYSQL_SYSVAR(log_file_size), | ||
| 26612 | MYSQL_SYSVAR(log_files_in_group), | ||
| 26613 | MYSQL_SYSVAR(redo_log_capacity), | ||
| 26614 | #ifdef UNIV_DEBUG_DEDICATED | ||
| 26615 | MYSQL_SYSVAR(debug_sys_mem_size), | ||
| 26616 | #endif /* UNIV_DEBUG_DEDICATED */ | ||
| 26617 | MYSQL_SYSVAR(log_write_ahead_size), | ||
| 26618 | MYSQL_SYSVAR(log_group_home_dir), | ||
| 26619 | MYSQL_SYSVAR(log_writer_threads), | ||
| 26620 | MYSQL_SYSVAR(log_spin_cpu_abs_lwm), | ||
| 26621 | MYSQL_SYSVAR(log_spin_cpu_pct_hwm), | ||
| 26622 | MYSQL_SYSVAR(log_wait_for_flush_spin_hwm), | ||
| 26623 | #ifdef ENABLE_EXPERIMENT_SYSVARS | ||
| 26624 | MYSQL_SYSVAR(log_write_events), | ||
| 26625 | MYSQL_SYSVAR(log_flush_events), | ||
| 26626 | MYSQL_SYSVAR(log_recent_written_size), | ||
| 26627 | MYSQL_SYSVAR(log_recent_closed_size), | ||
| 26628 | MYSQL_SYSVAR(log_wait_for_write_spin_delay), | ||
| 26629 | MYSQL_SYSVAR(log_wait_for_write_timeout), | ||
| 26630 | MYSQL_SYSVAR(log_wait_for_flush_spin_delay), | ||
| 26631 | MYSQL_SYSVAR(log_wait_for_flush_timeout), | ||
| 26632 | MYSQL_SYSVAR(log_write_max_size), | ||
| 26633 | MYSQL_SYSVAR(log_writer_spin_delay), | ||
| 26634 | MYSQL_SYSVAR(log_writer_timeout), | ||
| 26635 | MYSQL_SYSVAR(log_checkpoint_every), | ||
| 26636 | MYSQL_SYSVAR(log_flusher_spin_delay), | ||
| 26637 | MYSQL_SYSVAR(log_flusher_timeout), | ||
| 26638 | MYSQL_SYSVAR(log_write_notifier_spin_delay), | ||
| 26639 | MYSQL_SYSVAR(log_write_notifier_timeout), | ||
| 26640 | MYSQL_SYSVAR(log_flush_notifier_spin_delay), | ||
| 26641 | MYSQL_SYSVAR(log_flush_notifier_timeout), | ||
| 26642 | #endif /* ENABLE_EXPERIMENT_SYSVARS */ | ||
| 26643 | MYSQL_SYSVAR(log_compressed_pages), | ||
| 26644 | MYSQL_SYSVAR(max_dirty_pages_pct), | ||
| 26645 | MYSQL_SYSVAR(max_dirty_pages_pct_lwm), | ||
| 26646 | MYSQL_SYSVAR(adaptive_flushing_lwm), | ||
| 26647 | MYSQL_SYSVAR(adaptive_flushing), | ||
| 26648 | MYSQL_SYSVAR(flush_sync), | ||
| 26649 | MYSQL_SYSVAR(flushing_avg_loops), | ||
| 26650 | MYSQL_SYSVAR(max_purge_lag), | ||
| 26651 | MYSQL_SYSVAR(max_purge_lag_delay), | ||
| 26652 | MYSQL_SYSVAR(old_blocks_pct), | ||
| 26653 | MYSQL_SYSVAR(old_blocks_time), | ||
| 26654 | MYSQL_SYSVAR(open_files), | ||
| 26655 | MYSQL_SYSVAR(optimize_fulltext_only), | ||
| 26656 | MYSQL_SYSVAR(rollback_on_timeout), | ||
| 26657 | MYSQL_SYSVAR(ft_aux_table), | ||
| 26658 | MYSQL_SYSVAR(ft_enable_diag_print), | ||
| 26659 | MYSQL_SYSVAR(ft_server_stopword_table), | ||
| 26660 | MYSQL_SYSVAR(ft_user_stopword_table), | ||
| 26661 | MYSQL_SYSVAR(disable_sort_file_cache), | ||
| 26662 | MYSQL_SYSVAR(stats_on_metadata), | ||
| 26663 | MYSQL_SYSVAR(stats_transient_sample_pages), | ||
| 26664 | MYSQL_SYSVAR(stats_persistent), | ||
| 26665 | MYSQL_SYSVAR(stats_persistent_sample_pages), | ||
| 26666 | MYSQL_SYSVAR(stats_auto_recalc), | ||
| 26667 | MYSQL_SYSVAR(adaptive_hash_index), | ||
| 26668 | MYSQL_SYSVAR(adaptive_hash_index_parts), | ||
| 26669 | MYSQL_SYSVAR(stats_method), | ||
| 26670 | MYSQL_SYSVAR(replication_delay), | ||
| 26671 | MYSQL_SYSVAR(status_file), | ||
| 26672 | MYSQL_SYSVAR(strict_mode), | ||
| 26673 | MYSQL_SYSVAR(sort_buffer_size), | ||
| 26674 | MYSQL_SYSVAR(online_alter_log_max_size), | ||
| 26675 | MYSQL_SYSVAR(directories), | ||
| 26676 | MYSQL_SYSVAR(sync_spin_loops), | ||
| 26677 | MYSQL_SYSVAR(spin_wait_delay), | ||
| 26678 | MYSQL_SYSVAR(spin_wait_pause_multiplier), | ||
| 26679 | MYSQL_SYSVAR(fsync_threshold), | ||
| 26680 | MYSQL_SYSVAR(table_locks), | ||
| 26681 | MYSQL_SYSVAR(thread_concurrency), | ||
| 26682 | MYSQL_SYSVAR(adaptive_max_sleep_delay), | ||
| 26683 | MYSQL_SYSVAR(thread_sleep_delay), | ||
| 26684 | MYSQL_SYSVAR(tmpdir), | ||
| 26685 | MYSQL_SYSVAR(autoinc_lock_mode), | ||
| 26686 | MYSQL_SYSVAR(show_locks_held), | ||
| 26687 | MYSQL_SYSVAR(version), | ||
| 26688 | MYSQL_SYSVAR(use_native_aio), | ||
| 26689 | #ifdef HAVE_LIBNUMA | ||
| 26690 | MYSQL_SYSVAR(numa_interleave), | ||
| 26691 | #endif /* HAVE_LIBNUMA */ | ||
| 26692 | MYSQL_SYSVAR(change_buffering), | ||
| 26693 | MYSQL_SYSVAR(change_buffer_max_size), | ||
| 26694 | #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG | ||
| 26695 | MYSQL_SYSVAR(change_buffering_debug), | ||
| 26696 | MYSQL_SYSVAR(disable_background_merge), | ||
| 26697 | #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ | ||
| 26698 | #ifdef WITH_WSREP | ||
| 26699 | MYSQL_SYSVAR(disallow_writes), | ||
| 26700 | #endif /* WITH_WSREP */ | ||
| 26701 | MYSQL_SYSVAR(random_read_ahead), | ||
| 26702 | MYSQL_SYSVAR(read_ahead_threshold), | ||
| 26703 | MYSQL_SYSVAR(read_only), | ||
| 26704 | |||
| 26705 | MYSQL_SYSVAR(io_capacity), | ||
| 26706 | MYSQL_SYSVAR(io_capacity_max), | ||
| 26707 | MYSQL_SYSVAR(idle_flush_pct), | ||
| 26708 | MYSQL_SYSVAR(page_cleaners), | ||
| 26709 | MYSQL_SYSVAR(monitor_enable), | ||
| 26710 | MYSQL_SYSVAR(monitor_disable), | ||
| 26711 | MYSQL_SYSVAR(monitor_reset), | ||
| 26712 | MYSQL_SYSVAR(monitor_reset_all), | ||
| 26713 | MYSQL_SYSVAR(purge_threads), | ||
| 26714 | MYSQL_SYSVAR(purge_batch_size), | ||
| 26715 | #ifdef UNIV_DEBUG | ||
| 26716 | MYSQL_SYSVAR(background_drop_list_empty), | ||
| 26717 | MYSQL_SYSVAR(purge_run_now), | ||
| 26718 | MYSQL_SYSVAR(purge_stop_now), | ||
| 26719 | MYSQL_SYSVAR(log_flush_now), | ||
| 26720 | MYSQL_SYSVAR(log_checkpoint_now), | ||
| 26721 | MYSQL_SYSVAR(log_checkpoint_fuzzy_now), | ||
| 26722 | MYSQL_SYSVAR(checkpoint_disabled), | ||
| 26723 | MYSQL_SYSVAR(buf_flush_list_now), | ||
| 26724 | MYSQL_SYSVAR(merge_threshold_set_all_debug), | ||
| 26725 | MYSQL_SYSVAR(semaphore_wait_timeout_debug), | ||
| 26726 | #endif /* UNIV_DEBUG */ | ||
| 26727 | #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG | ||
| 26728 | MYSQL_SYSVAR(page_hash_locks), | ||
| 26729 | #ifdef UNIV_LINUX | ||
| 26730 | MYSQL_SYSVAR(sched_priority_purge), | ||
| 26731 | MYSQL_SYSVAR(sched_priority_io), | ||
| 26732 | MYSQL_SYSVAR(sched_priority_master), | ||
| 26733 | MYSQL_SYSVAR(priority_purge), | ||
| 26734 | MYSQL_SYSVAR(priority_master), | ||
| 26735 | #endif /* UNIV_LINUX */ | ||
| 26736 | MYSQL_SYSVAR(cleaner_max_lru_time), | ||
| 26737 | MYSQL_SYSVAR(cleaner_max_flush_time), | ||
| 26738 | #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */ | ||
| 26739 | MYSQL_SYSVAR(validate_tablespace_paths), | ||
| 26740 | MYSQL_SYSVAR(use_fdatasync), | ||
| 26741 | MYSQL_SYSVAR(status_output), | ||
| 26742 | MYSQL_SYSVAR(status_output_locks), | ||
| 26743 | MYSQL_SYSVAR(cleaner_lsn_age_factor), | ||
| 26744 | MYSQL_SYSVAR(empty_free_list_algorithm), | ||
| 26745 | MYSQL_SYSVAR(print_all_deadlocks), | ||
| 26746 | MYSQL_SYSVAR(print_lock_wait_timeout_info), | ||
| 26747 | MYSQL_SYSVAR(cmp_per_index_enabled), | ||
| 26748 | MYSQL_SYSVAR(max_undo_log_size), | ||
| 26749 | MYSQL_SYSVAR(purge_rseg_truncate_frequency), | ||
| 26750 | MYSQL_SYSVAR(undo_log_truncate), | ||
| 26751 | MYSQL_SYSVAR(undo_log_encrypt), | ||
| 26752 | MYSQL_SYSVAR(rollback_segments), | ||
| 26753 | MYSQL_SYSVAR(undo_directory), | ||
| 26754 | MYSQL_SYSVAR(temp_tablespaces_dir), | ||
| 26755 | MYSQL_SYSVAR(undo_tablespaces), | ||
| 26756 | MYSQL_SYSVAR(sync_array_size), | ||
| 26757 | MYSQL_SYSVAR(compression_failure_threshold_pct), | ||
| 26758 | MYSQL_SYSVAR(compression_pad_pct_max), | ||
| 26759 | MYSQL_SYSVAR(default_row_format), | ||
| 26760 | MYSQL_SYSVAR(redo_log_archive_dirs), | ||
| 26761 | MYSQL_SYSVAR(redo_log_encrypt), | ||
| 26762 | MYSQL_SYSVAR(print_ddl_logs), | ||
| 26763 | #ifdef UNIV_DEBUG | ||
| 26764 | MYSQL_SYSVAR(trx_rseg_n_slots_debug), | ||
| 26765 | MYSQL_SYSVAR(limit_optimistic_insert_debug), | ||
| 26766 | MYSQL_SYSVAR(trx_purge_view_update_only_debug), | ||
| 26767 | MYSQL_SYSVAR(fil_make_page_dirty_debug), | ||
| 26768 | MYSQL_SYSVAR(saved_page_number_debug), | ||
| 26769 | MYSQL_SYSVAR(compress_debug), | ||
| 26770 | MYSQL_SYSVAR(page_cleaner_disabled_debug), | ||
| 26771 | MYSQL_SYSVAR(dict_stats_disabled_debug), | ||
| 26772 | MYSQL_SYSVAR(master_thread_disabled_debug), | ||
| 26773 | MYSQL_SYSVAR(sync_debug), | ||
| 26774 | MYSQL_SYSVAR(buffer_pool_debug), | ||
| 26775 | MYSQL_SYSVAR(ddl_log_crash_reset_debug), | ||
| 26776 | MYSQL_SYSVAR(interpreter), | ||
| 26777 | MYSQL_SYSVAR(interpreter_output), | ||
| 26778 | #endif /* UNIV_DEBUG */ | ||
| 26779 | MYSQL_SYSVAR(parallel_read_threads), | ||
| 26780 | MYSQL_SYSVAR(segment_reserve_factor), | ||
| 26781 | MYSQL_SYSVAR(corrupt_table_action), | ||
| 26782 | MYSQL_SYSVAR(parallel_doublewrite_path), | ||
| 26783 | MYSQL_SYSVAR(parallel_dblwr_encrypt), | ||
| 26784 | MYSQL_SYSVAR(compressed_columns_zip_level), | ||
| 26785 | MYSQL_SYSVAR(compressed_columns_threshold), | ||
| 26786 | MYSQL_SYSVAR(ft_ignore_stopwords), | ||
| 26787 | MYSQL_SYSVAR(encrypt_online_alter_logs), | ||
| 26788 | MYSQL_SYSVAR(encryption_threads), | ||
| 26789 | MYSQL_SYSVAR(encryption_rotate_key_age), | ||
| 26790 | MYSQL_SYSVAR(encryption_rotation_iops), | ||
| 26791 | MYSQL_SYSVAR(default_encryption_key_id), | ||
| 26792 | MYSQL_SYSVAR(records_in_range), | ||
| 26793 | MYSQL_SYSVAR(force_index_records_in_range), | ||
| 26794 | nullptr}; | ||
| 26795 | |||
| 26796 | mysql_declare_plugin(innobase){ | ||
| 26797 | MYSQL_STORAGE_ENGINE_PLUGIN, | ||
| 26798 | &innobase_storage_engine, | ||
| 26799 | innobase_hton_name, | ||
| 26800 | PLUGIN_AUTHOR_ORACLE, | ||
| 26801 | "Percona-XtraDB, Supports transactions, row-level locking, and foreign " | ||
| 26802 | "keys", | ||
| 26803 | PLUGIN_LICENSE_GPL, | ||
| 26804 | innodb_init, /* Plugin Init */ | ||
| 26805 | nullptr, /* Plugin Check uninstall */ | ||
| 26806 | innodb_deinit, /* Plugin Deinit */ | ||
| 26807 | INNODB_VERSION_SHORT, | ||
| 26808 | innodb_status_variables_export, /* status variables */ | ||
| 26809 | innobase_system_variables, /* system variables */ | ||
| 26810 | nullptr, /* reserved */ | ||
| 26811 | 0, /* flags */ | ||
| 26812 | }, | ||
| 26813 | i_s_innodb_trx, i_s_innodb_cmp, i_s_innodb_cmp_reset, i_s_innodb_cmpmem, | ||
| 26814 | i_s_innodb_cmpmem_reset, i_s_innodb_cmp_per_index, | ||
| 26815 | i_s_innodb_cmp_per_index_reset, i_s_innodb_buffer_page, | ||
| 26816 | i_s_innodb_buffer_page_lru, i_s_innodb_buffer_stats, | ||
| 26817 | i_s_innodb_temp_table_info, i_s_innodb_metrics, | ||
| 26818 | i_s_innodb_ft_default_stopword, i_s_innodb_ft_deleted, | ||
| 26819 | i_s_innodb_ft_being_deleted, i_s_innodb_ft_config, | ||
| 26820 | i_s_innodb_ft_index_cache, i_s_innodb_ft_index_table, i_s_innodb_tables, | ||
| 26821 | i_s_innodb_tablestats, i_s_innodb_indexes, i_s_innodb_tablespaces, | ||
| 26822 | i_s_innodb_columns, i_s_innodb_virtual, i_s_innodb_cached_indexes, | ||
| 26823 | i_s_innodb_session_temp_tablespaces, | ||
| 26824 | i_s_innodb_tablespaces_encryption | ||
| 26825 | |||
| 26826 | mysql_declare_plugin_end; | ||
| 26827 | |||
| 26828 | /** @brief Initialize the default value of innodb_commit_concurrency. | ||
| 26829 | |||
| 26830 | Once InnoDB is running, the innodb_commit_concurrency must not change | ||
| 26831 | from zero to nonzero. (Bug #42101) | ||
| 26832 | |||
| 26833 | The initial default value is 0, and without this extra initialization, | ||
| 26834 | SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter | ||
| 26835 | to 0, even if it was initially set to nonzero at the command line | ||
| 26836 | or configuration file. */ | ||
| 26837 | 9726 | static void innobase_commit_concurrency_init_default() { | |
| 26838 | 9726 | MYSQL_SYSVAR_NAME(commit_concurrency).def_val = innobase_commit_concurrency; | |
| 26839 | 9726 | } | |
| 26840 | |||
| 26841 | /**************************************************************************** | ||
| 26842 | DS-MRR implementation | ||
| 26843 | ***************************************************************************/ | ||
| 26844 | |||
| 26845 | /** | ||
| 26846 | Multi Range Read interface, DS-MRR calls */ | ||
| 26847 | 632328 | int ha_innobase::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param, | |
| 26848 | uint n_ranges, uint mode, | ||
| 26849 | HANDLER_BUFFER *buf) { | ||
| 26850 | 632328 | m_ds_mrr.init(table); | |
| 26851 | |||
| 26852 | 632361 | return (m_ds_mrr.dsmrr_init(seq, seq_init_param, n_ranges, mode, buf)); | |
| 26853 | } | ||
| 26854 | |||
| 26855 | 3729039 | int ha_innobase::multi_range_read_next(char **range_info) { | |
| 26856 | 3729039 | return (m_ds_mrr.dsmrr_next(range_info)); | |
| 26857 | } | ||
| 26858 | |||
| 26859 | 613359 | ha_rows ha_innobase::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, | |
| 26860 | void *seq_init_param, | ||
| 26861 | uint n_ranges, uint *bufsz, | ||
| 26862 | uint *flags, | ||
| 26863 | Cost_estimate *cost) { | ||
| 26864 | /* See comments in ha_myisam::multi_range_read_info_const */ | ||
| 26865 | 613359 | m_ds_mrr.init(table); | |
| 26866 | |||
| 26867 | 613396 | return (m_ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz, | |
| 26868 | 613460 | flags, cost)); | |
| 26869 | } | ||
| 26870 | |||
| 26871 | 4106 | ha_rows ha_innobase::multi_range_read_info(uint keyno, uint n_ranges, uint keys, | |
| 26872 | uint *bufsz, uint *flags, | ||
| 26873 | Cost_estimate *cost) { | ||
| 26874 | 4106 | m_ds_mrr.init(table); | |
| 26875 | |||
| 26876 | 4106 | return (m_ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost)); | |
| 26877 | } | ||
| 26878 | |||
| 26879 | /** | ||
| 26880 | Index Condition Pushdown interface implementation */ | ||
| 26881 | |||
| 26882 | /** InnoDB index push-down condition check | ||
| 26883 | @return ICP_NO_MATCH, ICP_MATCH, or ICP_OUT_OF_RANGE */ | ||
| 26884 | ICP_RESULT | ||
| 26885 | 1115590 | innobase_index_cond(ha_innobase *h) /*!< in/out: pointer to ha_innobase */ | |
| 26886 | { | ||
| 26887 |
1/2✓ Branch 0 taken 1115590 times.
✗ Branch 1 not taken.
|
1115590 | DBUG_TRACE; |
| 26888 | |||
| 26889 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1115590 times.
|
1115590 | assert(h->pushed_idx_cond); |
| 26890 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1115590 times.
|
1115590 | assert(h->pushed_idx_cond_keyno != MAX_KEY); |
| 26891 | |||
| 26892 |
7/8✓ Branch 0 taken 7880 times.
✓ Branch 1 taken 1107710 times.
✓ Branch 2 taken 7880 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 828 times.
✓ Branch 5 taken 7052 times.
✓ Branch 6 taken 828 times.
✓ Branch 7 taken 1114762 times.
|
1115590 | if (h->end_range && h->compare_key_icp(h->end_range) > 0) { |
| 26893 | /* caller should return HA_ERR_END_OF_FILE already */ | ||
| 26894 | 828 | return ICP_OUT_OF_RANGE; | |
| 26895 | } | ||
| 26896 | |||
| 26897 |
3/4✓ Branch 0 taken 1114762 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1112998 times.
✓ Branch 3 taken 1764 times.
|
1114762 | return h->pushed_idx_cond->val_int() ? ICP_MATCH : ICP_NO_MATCH; |
| 26898 | 1115590 | } | |
| 26899 | |||
| 26900 | /** Get the computed value by supplying the base column values. | ||
| 26901 | @param[in,out] table the table whose virtual column template to be built */ | ||
| 26902 | 2 | void innobase_init_vc_templ(dict_table_t *table) { | |
| 26903 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | dict_sys_mutex_enter(); |
| 26904 | |||
| 26905 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (table->vc_templ != nullptr) { |
| 26906 | ✗ | dict_sys_mutex_exit(); | |
| 26907 | |||
| 26908 | ✗ | return; | |
| 26909 | } | ||
| 26910 | |||
| 26911 | 2 | table->vc_templ = | |
| 26912 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ut::new_withkey<dict_vcol_templ_t>(UT_NEW_THIS_FILE_PSI_KEY); |
| 26913 | 2 | table->vc_templ->vtempl = nullptr; | |
| 26914 | |||
| 26915 | 2 | std::string schema_name; | |
| 26916 | 2 | std::string table_name; | |
| 26917 | |||
| 26918 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | table->get_table_name(schema_name, table_name); |
| 26919 | |||
| 26920 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | THD *thd = current_thd; |
| 26921 | |||
| 26922 | { | ||
| 26923 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | innodb_session_dict_mutex_guard_t guard(*thd_to_innodb_session(thd)); |
| 26924 | #ifdef UNIV_DEBUG | ||
| 26925 | bool ret = | ||
| 26926 | #endif /* UNIV_DEBUG */ | ||
| 26927 | |||
| 26928 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | handler::my_prepare_gcolumn_template( |
| 26929 | thd, schema_name.c_str(), table_name.c_str(), | ||
| 26930 | &innobase_build_v_templ_callback, static_cast<void *>(table)); | ||
| 26931 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | ut_ad(!ret); |
| 26932 | 2 | } | |
| 26933 | |||
| 26934 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | dict_sys_mutex_exit(); |
| 26935 | 2 | } | |
| 26936 | |||
| 26937 | /** Change dbname and table name in table->vc_templ. | ||
| 26938 | @param[in,out] table the table whose virtual column template | ||
| 26939 | dbname and tbname to be renamed. */ | ||
| 26940 | 752 | void innobase_rename_vc_templ(dict_table_t *table) { | |
| 26941 | 752 | std::string schema_name; | |
| 26942 | 752 | std::string table_name; | |
| 26943 | |||
| 26944 | /* Get table and schema name in system character set. */ | ||
| 26945 |
1/2✓ Branch 0 taken 752 times.
✗ Branch 1 not taken.
|
752 | table->get_table_name(schema_name, table_name); |
| 26946 | |||
| 26947 |
1/2✓ Branch 0 taken 752 times.
✗ Branch 1 not taken.
|
752 | table->vc_templ->db_name.assign(schema_name); |
| 26948 |
1/2✓ Branch 0 taken 752 times.
✗ Branch 1 not taken.
|
752 | table->vc_templ->tb_name.assign(table_name); |
| 26949 | 752 | } | |
| 26950 | |||
| 26951 | 85 | dfield_t *innobase_get_field_from_update_vector(dict_foreign_t *foreign, | |
| 26952 | upd_t *update, | ||
| 26953 | uint32_t col_no) { | ||
| 26954 | 85 | dict_table_t *parent_table = foreign->referenced_table; | |
| 26955 | 85 | dict_index_t *parent_index = foreign->referenced_index; | |
| 26956 | uint32_t parent_field_no; | ||
| 26957 | uint32_t parent_col_no; | ||
| 26958 | uint32_t child_col_no; | ||
| 26959 | |||
| 26960 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 23 times.
|
108 | for (uint32_t i = 0; i < foreign->n_fields; i++) { |
| 26961 | 85 | child_col_no = foreign->foreign_index->get_col_no(i); | |
| 26962 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 62 times.
|
85 | if (child_col_no != col_no) { |
| 26963 | 23 | continue; | |
| 26964 | } | ||
| 26965 | 62 | parent_col_no = parent_index->get_col_no(i); | |
| 26966 | 62 | parent_field_no = dict_table_get_nth_col_pos(parent_table, parent_col_no); | |
| 26967 |
1/2✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
|
62 | for (uint32_t j = 0; j < update->n_fields; j++) { |
| 26968 | 62 | upd_field_t *parent_ufield = &update->fields[j]; | |
| 26969 |
1/2✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
|
62 | if (parent_ufield->field_no == parent_field_no) { |
| 26970 | 62 | return (&parent_ufield->new_val); | |
| 26971 | } | ||
| 26972 | } | ||
| 26973 | } | ||
| 26974 | |||
| 26975 | 23 | return (nullptr); | |
| 26976 | } | ||
| 26977 | |||
| 26978 | /** Get the computed value by supplying the base column values. | ||
| 26979 | @param[in,out] row the data row | ||
| 26980 | @param[in] col virtual column | ||
| 26981 | @param[in] index index on the virtual column | ||
| 26982 | @param[in,out] local_heap heap memory for processing large data etc. | ||
| 26983 | @param[in,out] heap memory heap that copies the actual index row | ||
| 26984 | @param[in] ifield index field | ||
| 26985 | @param[in] thd MySQL thread handle | ||
| 26986 | @param[in,out] mysql_table mysql table object | ||
| 26987 | @param[in] old_table during ALTER TABLE, this is the old table | ||
| 26988 | or NULL. | ||
| 26989 | @param[in] parent_update update vector for the parent row | ||
| 26990 | @param[in] foreign foreign key information | ||
| 26991 | @param[in] compress_heap | ||
| 26992 | @return the field filled with computed value, or NULL if just want | ||
| 26993 | to store the value in passed in "my_rec" */ | ||
| 26994 | 29708 | dfield_t *innobase_get_computed_value( | |
| 26995 | const dtuple_t *row, const dict_v_col_t *col, const dict_index_t *index, | ||
| 26996 | mem_heap_t **local_heap, mem_heap_t *heap, const dict_field_t *ifield, | ||
| 26997 | THD *thd, TABLE *mysql_table, const dict_table_t *old_table, | ||
| 26998 | upd_t *parent_update, dict_foreign_t *foreign, mem_heap_t **compress_heap) { | ||
| 26999 | byte rec_buf1[REC_VERSION_56_MAX_INDEX_COL_LEN]; | ||
| 27000 | byte rec_buf2[REC_VERSION_56_MAX_INDEX_COL_LEN]; | ||
| 27001 | byte *mysql_rec; | ||
| 27002 | byte *buf; | ||
| 27003 | dfield_t *field; | ||
| 27004 | ulint len; | ||
| 27005 | 29708 | ulong mv_length = 0; | |
| 27006 | 29708 | const char *mv_data_ptr = nullptr; | |
| 27007 | |||
| 27008 | const page_size_t page_size = (old_table == nullptr) | ||
| 27009 |
1/2✓ Branch 0 taken 3158 times.
✗ Branch 1 not taken.
|
3158 | ? dict_table_page_size(index->table) |
| 27010 |
3/4✓ Branch 0 taken 3158 times.
✓ Branch 1 taken 26550 times.
✓ Branch 2 taken 26550 times.
✗ Branch 3 not taken.
|
29708 | : dict_table_page_size(old_table); |
| 27011 | |||
| 27012 | 29708 | const dict_index_t *clust_index = nullptr; | |
| 27013 |
2/2✓ Branch 0 taken 3158 times.
✓ Branch 1 taken 26550 times.
|
29708 | if (old_table == nullptr) { |
| 27014 |
1/2✓ Branch 0 taken 3158 times.
✗ Branch 1 not taken.
|
3158 | clust_index = index->table->first_index(); |
| 27015 | } else { | ||
| 27016 |
1/2✓ Branch 0 taken 26550 times.
✗ Branch 1 not taken.
|
26550 | clust_index = old_table->first_index(); |
| 27017 | } | ||
| 27018 | |||
| 27019 | 29708 | ulint ret = 0; | |
| 27020 | |||
| 27021 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29708 times.
|
29708 | ut_ad(index->table->vc_templ); |
| 27022 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29708 times.
|
29708 | ut_ad(thd != nullptr); |
| 27023 | |||
| 27024 | 29708 | const mysql_row_templ_t *vctempl = | |
| 27025 | 29708 | index->table->vc_templ | |
| 27026 | 29708 | ->vtempl[index->table->vc_templ->n_col + col->v_pos]; | |
| 27027 | |||
| 27028 |
2/2✓ Branch 0 taken 28307 times.
✓ Branch 1 taken 1401 times.
|
29708 | if (!heap || |
| 27029 |
2/2✓ Branch 0 taken 1619 times.
✓ Branch 1 taken 26688 times.
|
28307 | index->table->vc_templ->rec_len >= REC_VERSION_56_MAX_INDEX_COL_LEN) { |
| 27030 |
2/2✓ Branch 0 taken 978 times.
✓ Branch 1 taken 2042 times.
|
3020 | if (*local_heap == nullptr) { |
| 27031 |
1/2✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
|
978 | *local_heap = mem_heap_create(UNIV_PAGE_SIZE, UT_LOCATION_HERE); |
| 27032 | } | ||
| 27033 | |||
| 27034 | mysql_rec = static_cast<byte *>( | ||
| 27035 |
1/2✓ Branch 0 taken 3020 times.
✗ Branch 1 not taken.
|
3020 | mem_heap_alloc(*local_heap, index->table->vc_templ->rec_len)); |
| 27036 | 3020 | buf = static_cast<byte *>( | |
| 27037 |
1/2✓ Branch 0 taken 3020 times.
✗ Branch 1 not taken.
|
3020 | mem_heap_alloc(*local_heap, index->table->vc_templ->rec_len)); |
| 27038 | } else { | ||
| 27039 | 26688 | mysql_rec = rec_buf1; | |
| 27040 | 26688 | buf = rec_buf2; | |
| 27041 | } | ||
| 27042 | |||
| 27043 |
2/2✓ Branch 0 taken 31136 times.
✓ Branch 1 taken 29708 times.
|
60844 | for (ulint i = 0; i < col->num_base; i++) { |
| 27044 | 31136 | dict_col_t *base_col = col->base_col[i]; | |
| 27045 | 31136 | const dfield_t *row_field = nullptr; | |
| 27046 | 31136 | uint32_t col_no = base_col->ind; | |
| 27047 | 31136 | const mysql_row_templ_t *templ = index->table->vc_templ->vtempl[col_no]; | |
| 27048 | const byte *data; | ||
| 27049 | |||
| 27050 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 31055 times.
|
31136 | if (parent_update != nullptr) { |
| 27051 | row_field = | ||
| 27052 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | innobase_get_field_from_update_vector(foreign, parent_update, col_no); |
| 27053 | } | ||
| 27054 | |||
| 27055 |
2/2✓ Branch 0 taken 31076 times.
✓ Branch 1 taken 60 times.
|
31136 | if (row_field == nullptr) { |
| 27056 |
1/2✓ Branch 0 taken 31076 times.
✗ Branch 1 not taken.
|
31076 | row_field = dtuple_get_nth_field(row, col_no); |
| 27057 | } | ||
| 27058 | |||
| 27059 | 31136 | data = static_cast<const byte *>(row_field->data); | |
| 27060 | 31136 | len = row_field->len; | |
| 27061 | |||
| 27062 |
2/2✓ Branch 0 taken 67 times.
✓ Branch 1 taken 31069 times.
|
31136 | if (row_field->ext) { |
| 27063 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 59 times.
|
67 | if (*local_heap == nullptr) { |
| 27064 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | *local_heap = mem_heap_create(UNIV_PAGE_SIZE, UT_LOCATION_HERE); |
| 27065 | } | ||
| 27066 | |||
| 27067 | 67 | data = lob::btr_copy_externally_stored_field( | |
| 27068 |
1/2✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
|
67 | thd_to_trx(thd), clust_index, &len, nullptr, data, page_size, |
| 27069 |
2/4✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
|
67 | dfield_get_len(row_field), false, *local_heap); |
| 27070 | } | ||
| 27071 | |||
| 27072 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 31067 times.
|
31136 | if (len == UNIV_SQL_NULL) { |
| 27073 | 69 | mysql_rec[templ->mysql_null_byte_offset] |= | |
| 27074 | 69 | (byte)templ->mysql_null_bit_mask; | |
| 27075 | 69 | memcpy(mysql_rec + templ->mysql_col_offset, | |
| 27076 | 69 | static_cast<const byte *>(index->table->vc_templ->default_rec + | |
| 27077 | 69 | templ->mysql_col_offset), | |
| 27078 | 69 | templ->mysql_col_len); | |
| 27079 | } else { | ||
| 27080 | 31067 | row_sel_field_store_in_mysql_format( | |
| 27081 | 31067 | mysql_rec + templ->mysql_col_offset, templ, index, | |
| 27082 |
1/2✓ Branch 0 taken 31067 times.
✗ Branch 1 not taken.
|
31067 | templ->clust_rec_field_no, (const byte *)data, len, compress_heap, |
| 27083 | ULINT_UNDEFINED); | ||
| 27084 | |||
| 27085 |
2/2✓ Branch 0 taken 14724 times.
✓ Branch 1 taken 16343 times.
|
31067 | if (templ->mysql_null_bit_mask) { |
| 27086 | /* It is a nullable column with a | ||
| 27087 | non-NULL value */ | ||
| 27088 | 14724 | mysql_rec[templ->mysql_null_byte_offset] &= | |
| 27089 | 14724 | ~(byte)templ->mysql_null_bit_mask; | |
| 27090 | } | ||
| 27091 | } | ||
| 27092 | } | ||
| 27093 | |||
| 27094 |
1/2✓ Branch 0 taken 29708 times.
✗ Branch 1 not taken.
|
29708 | field = dtuple_get_nth_v_field(row, col->v_pos); |
| 27095 | |||
| 27096 | /* Bitmap for specifying which virtual columns the server | ||
| 27097 | should evaluate */ | ||
| 27098 | 29708 | MY_BITMAP column_map; | |
| 27099 | my_bitmap_map col_map_storage[bitmap_buffer_size(REC_MAX_N_FIELDS)]; | ||
| 27100 | |||
| 27101 |
1/2✓ Branch 0 taken 29708 times.
✗ Branch 1 not taken.
|
29708 | bitmap_init(&column_map, col_map_storage, REC_MAX_N_FIELDS); |
| 27102 | |||
| 27103 | /* Specify the column the server should evaluate */ | ||
| 27104 | 29708 | bitmap_set_bit(&column_map, col->m_col.ind); | |
| 27105 | |||
| 27106 | 29708 | Temp_table_handle tblhdl; | |
| 27107 | |||
| 27108 |
2/2✓ Branch 0 taken 202 times.
✓ Branch 1 taken 29506 times.
|
29708 | if (mysql_table == nullptr) { |
| 27109 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 202 times.
|
202 | if (vctempl->type == DATA_BLOB) { |
| 27110 | ulint max_len; | ||
| 27111 | |||
| 27112 | ✗ | if (vctempl->mysql_col_len - 8 == 1) { | |
| 27113 | /* This is for TINYBLOB only, which needs | ||
| 27114 | only 1 byte, other BLOBs won't be affected */ | ||
| 27115 | ✗ | max_len = 255; | |
| 27116 | } else { | ||
| 27117 | ✗ | max_len = DICT_MAX_FIELD_LEN_BY_FORMAT(index->table) + 1; | |
| 27118 | } | ||
| 27119 | |||
| 27120 | ✗ | byte *blob_mem = static_cast<byte *>(mem_heap_alloc(heap, max_len)); | |
| 27121 | |||
| 27122 | ✗ | row_mysql_store_blob_ref(mysql_rec + vctempl->mysql_col_offset, | |
| 27123 | ✗ | vctempl->mysql_col_len, blob_mem, max_len, false, | |
| 27124 | 0, 0, compress_heap); | ||
| 27125 | } | ||
| 27126 | |||
| 27127 | /* open a temporary table handle */ | ||
| 27128 |
1/2✓ Branch 0 taken 202 times.
✗ Branch 1 not taken.
|
202 | mysql_table = tblhdl.open(thd, index->table->vc_templ->db_name.c_str(), |
| 27129 | 202 | index->table->vc_templ->tb_name.c_str()); | |
| 27130 | } | ||
| 27131 |
1/2✓ Branch 0 taken 29708 times.
✗ Branch 1 not taken.
|
29708 | if (mysql_table) { |
| 27132 |
5/6✓ Branch 0 taken 25433 times.
✓ Branch 1 taken 4275 times.
✓ Branch 2 taken 25433 times.
✓ Branch 3 taken 4275 times.
✓ Branch 4 taken 29708 times.
✗ Branch 5 not taken.
|
59416 | ret = handler::my_eval_gcolumn_expr( |
| 27133 | thd, mysql_table, &column_map, (uchar *)mysql_rec, | ||
| 27134 | 29708 | (col->m_col.is_multi_value() ? &mv_data_ptr : nullptr), | |
| 27135 | 29708 | (col->m_col.is_multi_value() ? &mv_length : nullptr)); | |
| 27136 | } else { | ||
| 27137 | ✗ | return nullptr; | |
| 27138 | } | ||
| 27139 | |||
| 27140 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 29674 times.
|
29708 | if (ret != 0) { |
| 27141 | #ifdef INNODB_VIRTUAL_DEBUG | ||
| 27142 | ib::warn(ER_IB_MSG_581) << "Compute virtual column values failed "; | ||
| 27143 | fputs("InnoDB: Cannot compute value for following record ", stderr); | ||
| 27144 | dtuple_print(stderr, row); | ||
| 27145 | #endif /* INNODB_VIRTUAL_DEBUG */ | ||
| 27146 | 34 | return (nullptr); | |
| 27147 | } | ||
| 27148 | |||
| 27149 |
2/2✓ Branch 0 taken 29572 times.
✓ Branch 1 taken 102 times.
|
29674 | if (vctempl->mysql_null_bit_mask && |
| 27150 | 29572 | (mysql_rec[vctempl->mysql_null_byte_offset] & | |
| 27151 |
2/2✓ Branch 0 taken 125 times.
✓ Branch 1 taken 29447 times.
|
29572 | vctempl->mysql_null_bit_mask)) { |
| 27152 |
1/2✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
|
125 | dfield_set_null(field); |
| 27153 | 125 | field->type.prtype |= DATA_VIRTUAL; | |
| 27154 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 59 times.
|
125 | if (col->m_col.is_multi_value()) { |
| 27155 | 66 | field->type.prtype |= DATA_MULTI_VALUE; | |
| 27156 | } | ||
| 27157 | 125 | return (field); | |
| 27158 | } | ||
| 27159 | |||
| 27160 |
2/2✓ Branch 0 taken 25339 times.
✓ Branch 1 taken 4210 times.
|
29549 | if (col->m_col.is_multi_value()) { |
| 27161 | Field_typed_array *fld; | ||
| 27162 | 25339 | fld = down_cast<Field_typed_array *>(mysql_table->field[col->m_col.ind]); | |
| 27163 |
1/2✓ Branch 0 taken 25339 times.
✗ Branch 1 not taken.
|
25339 | json_binary::Value v(json_binary::parse_binary(mv_data_ptr, mv_length)); |
| 27164 | 25339 | multi_value_data *value = nullptr; | |
| 27165 | |||
| 27166 | 50678 | bool succ = innobase_store_multi_value( | |
| 27167 |
2/4✓ Branch 0 taken 25339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25339 times.
✗ Branch 3 not taken.
|
25339 | v, value, fld, field, dict_table_is_comp(index->table), heap); |
| 27168 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25339 times.
|
25339 | if (!succ) { |
| 27169 | ✗ | ut_error; | |
| 27170 | } | ||
| 27171 | |||
| 27172 | 25339 | field->type.prtype |= DATA_MULTI_VALUE; | |
| 27173 | } else { | ||
| 27174 | 4210 | row_mysql_store_col_in_innobase_format( | |
| 27175 | 4210 | field, buf, true, mysql_rec + vctempl->mysql_col_offset, | |
| 27176 |
2/4✓ Branch 0 taken 4210 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4210 times.
✗ Branch 3 not taken.
|
4210 | vctempl->mysql_col_len, dict_table_is_comp(index->table), false, |
| 27177 | nullptr, 0, nullptr); | ||
| 27178 | } | ||
| 27179 | 29549 | field->type.prtype |= DATA_VIRTUAL; | |
| 27180 | |||
| 27181 | 29549 | ulint max_prefix = col->m_col.max_prefix; | |
| 27182 | |||
| 27183 |
4/4✓ Branch 0 taken 2506 times.
✓ Branch 1 taken 27043 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 2448 times.
|
29549 | if (max_prefix && ifield && |
| 27184 |
2/4✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 58 times.
|
58 | (ifield->prefix_len == 0 || ifield->prefix_len > col->m_col.max_prefix)) { |
| 27185 | ✗ | max_prefix = ifield->prefix_len; | |
| 27186 | } | ||
| 27187 | |||
| 27188 | /* If this is a prefix index, we only need a portion of the field */ | ||
| 27189 |
2/2✓ Branch 0 taken 2506 times.
✓ Branch 1 taken 27043 times.
|
29549 | if (max_prefix) { |
| 27190 | 5012 | len = dtype_get_at_most_n_mbchars( | |
| 27191 | 2506 | col->m_col.prtype, col->m_col.mbminmaxlen, max_prefix, field->len, | |
| 27192 |
2/4✓ Branch 0 taken 2506 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2506 times.
✗ Branch 3 not taken.
|
2506 | static_cast<char *>(dfield_get_data(field))); |
| 27193 |
1/2✓ Branch 0 taken 2506 times.
✗ Branch 1 not taken.
|
2506 | dfield_set_len(field, len); |
| 27194 | } | ||
| 27195 | |||
| 27196 |
7/8✓ Branch 0 taken 28205 times.
✓ Branch 1 taken 1344 times.
✓ Branch 2 taken 28205 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2866 times.
✓ Branch 5 taken 25339 times.
✓ Branch 6 taken 2866 times.
✓ Branch 7 taken 26683 times.
|
29549 | if (heap != nullptr && !dfield_is_multi_value(field)) { |
| 27197 |
1/2✓ Branch 0 taken 2866 times.
✗ Branch 1 not taken.
|
2866 | dfield_dup(field, heap); |
| 27198 | } | ||
| 27199 | |||
| 27200 | 29549 | return (field); | |
| 27201 | 29708 | } | |
| 27202 | |||
| 27203 | /** Attempt to push down an index condition. | ||
| 27204 | @param[in] keyno MySQL key number | ||
| 27205 | @param[in] idx_cond Index condition to be checked | ||
| 27206 | @return idx_cond if pushed; NULL if not pushed */ | ||
| 27207 | 2979 | class Item *ha_innobase::idx_cond_push(uint keyno, class Item *idx_cond) { | |
| 27208 |
1/2✓ Branch 0 taken 2979 times.
✗ Branch 1 not taken.
|
2979 | DBUG_TRACE; |
| 27209 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2979 times.
|
2979 | assert(keyno != MAX_KEY); |
| 27210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2979 times.
|
2979 | assert(idx_cond != nullptr); |
| 27211 | |||
| 27212 | 2979 | pushed_idx_cond = idx_cond; | |
| 27213 | 2979 | pushed_idx_cond_keyno = keyno; | |
| 27214 | 2979 | in_range_check_pushed_down = true; | |
| 27215 | /* We will evaluate the condition entirely */ | ||
| 27216 | 2979 | return nullptr; | |
| 27217 | 2979 | } | |
| 27218 | |||
| 27219 | /** Find out if a Record_buffer is wanted by this handler, and what is the | ||
| 27220 | maximum buffer size the handler wants. | ||
| 27221 | |||
| 27222 | @param[out] max_rows gets set to the maximum number of records to allocate | ||
| 27223 | space for in the buffer | ||
| 27224 | @retval true if the handler wants a buffer | ||
| 27225 | @retval false if the handler does not want a buffer */ | ||
| 27226 | 663060 | bool ha_innobase::is_record_buffer_wanted(ha_rows *const max_rows) const { | |
| 27227 | /* If the scan won't be able to utilize the record buffer, return that | ||
| 27228 | we don't want one. The decision on whether to use a buffer is taken in | ||
| 27229 | row_search_mvcc(), look for the comment that starts with "Decide | ||
| 27230 | whether to prefetch extra rows." Let's do the same check here. */ | ||
| 27231 | |||
| 27232 |
2/2✓ Branch 0 taken 411215 times.
✓ Branch 1 taken 251873 times.
|
663060 | if (!m_prebuilt->can_prefetch_records()) { |
| 27233 | 411215 | *max_rows = 0; | |
| 27234 | 411215 | return false; | |
| 27235 | } | ||
| 27236 | |||
| 27237 | /* Limit the number of rows in the buffer to 100 for now. We may want | ||
| 27238 | to fine-tune this later, possibly taking record size and page size into | ||
| 27239 | account. The optimizer might allocate an even smaller buffer if it | ||
| 27240 | thinks a smaller number of rows will be fetched. */ | ||
| 27241 | 251873 | *max_rows = 100; | |
| 27242 | 251873 | return true; | |
| 27243 | } | ||
| 27244 | |||
| 27245 | /** Return max limits for a single set of multi-valued keys | ||
| 27246 | @param[out] num_keys number of keys to store | ||
| 27247 | @param[out] keys_length total length of keys, bytes | ||
| 27248 | */ | ||
| 27249 | 28016 | void ha_innobase::mv_key_capacity(uint *num_keys, size_t *keys_length) const { | |
| 27250 | /* The limit of multi-value should be checked against undo page size, | ||
| 27251 | because a record length can not be longer than an undo page size. | ||
| 27252 | Actually, it should not be longer than half of a page size, but this | ||
| 27253 | can be checked for the full record. | ||
| 27254 | |||
| 27255 | The problem is, even if the number of multi-value fields are known, | ||
| 27256 | the actual number of multiple values per field are not known until | ||
| 27257 | the record itself gets inserted. So it's impossible to estimate the | ||
| 27258 | accurate max number of multiple values. Meanwhile, since other fields | ||
| 27259 | are not known in advance, so it's also impossible to estimate the | ||
| 27260 | accurate total key length. | ||
| 27261 | |||
| 27262 | Therefore, only the best effort can be done in this function. | ||
| 27263 | That is the estimation will be based on the INSERT to the table. | ||
| 27264 | And excluding all must have space, the left length is regarded | ||
| 27265 | as the keys_length. And the number of the keys would be got by | ||
| 27266 | keys_length / min(multi-value fields' length). Note if it is a | ||
| 27267 | variable length field, then it's data length is regarded as 1. | ||
| 27268 | |||
| 27269 | Furthermore, to make the calculation as simple as possible, some | ||
| 27270 | space cost would be ignored. This should not be a big deal, since | ||
| 27271 | the whole estimation is only a rough one. | ||
| 27272 | |||
| 27273 | So it's the greedy estimation which will try to give a most relaxed | ||
| 27274 | restriction on the table, to allow insert and update go as more as | ||
| 27275 | possible. The DB_UNDO_RECORD_TOO_BIG error would be raised if the | ||
| 27276 | actual user record exceeds the undo page size. */ | ||
| 27277 | |||
| 27278 | 28016 | size_t free_space = trx_undo_max_free_space(); | |
| 27279 | |||
| 27280 | /* PK always takes place in log page, take that into account */ | ||
| 27281 | 28016 | uint pk = table->s->primary_key; | |
| 27282 |
2/2✓ Branch 0 taken 17591 times.
✓ Branch 1 taken 10425 times.
|
28016 | if (pk != MAX_KEY) { |
| 27283 | 17591 | free_space -= table->s->key_info[pk].key_length; | |
| 27284 | } else { | ||
| 27285 | /* Deduct default InnoDB's PK length */ | ||
| 27286 | 10425 | free_space -= DATA_ROW_ID_LEN; | |
| 27287 | } | ||
| 27288 | |||
| 27289 | /* Maybe the space for any normal virtual columns etc. should be | ||
| 27290 | considered here, however, no details can be know at this time point, | ||
| 27291 | so just ignore them all */ | ||
| 27292 | |||
| 27293 | /* Find out the minimum key length so to get the maximum number | ||
| 27294 | of keys */ | ||
| 27295 | 28016 | uint16_t min_mv_key_length = std::numeric_limits<uint16_t>::max(); | |
| 27296 | |||
| 27297 |
2/2✓ Branch 0 taken 89300 times.
✓ Branch 1 taken 26601 times.
|
115901 | for (uint16_t i = 0; i < table->s->fields; ++i) { |
| 27298 | 89300 | Field *field = table->field[i]; | |
| 27299 |
2/2✓ Branch 0 taken 61008 times.
✓ Branch 1 taken 28292 times.
|
89300 | if (!innobase_is_multi_value_fld(field)) { |
| 27300 | 61008 | continue; | |
| 27301 | } | ||
| 27302 | |||
| 27303 | /* In case of variable length type, assume the minimum length of data, | ||
| 27304 | to make a maximum estimation of keys and allow users to insert as | ||
| 27305 | many keys as possible, under the constraint of total key length. */ | ||
| 27306 |
2/2✓ Branch 0 taken 1415 times.
✓ Branch 1 taken 26877 times.
|
28292 | if (field->type() == MYSQL_TYPE_VARCHAR) { |
| 27307 | 1415 | min_mv_key_length = 1; | |
| 27308 | 1415 | break; | |
| 27309 | } | ||
| 27310 | |||
| 27311 |
2/2✓ Branch 0 taken 26786 times.
✓ Branch 1 taken 91 times.
|
26877 | if (min_mv_key_length > field->key_length()) { |
| 27312 | 26786 | min_mv_key_length = field->key_length(); | |
| 27313 | } | ||
| 27314 | } | ||
| 27315 | |||
| 27316 | 28016 | *keys_length = Multi_value_logger::get_keys_capacity( | |
| 27317 | static_cast<uint32_t>(free_space), min_mv_key_length, num_keys); | ||
| 27318 | 28016 | } | |
| 27319 | |||
| 27320 | /** Use this when the args are passed to the format string from | ||
| 27321 | messages_to_clients.txt directly as is. | ||
| 27322 | |||
| 27323 | Push a warning message to the client, it is a wrapper around: | ||
| 27324 | |||
| 27325 | void push_warning_printf( | ||
| 27326 | THD *thd, Sql_condition::enum_condition_level level, | ||
| 27327 | uint code, const char *format, ...); | ||
| 27328 | */ | ||
| 27329 | 2887 | void ib_senderrf(THD *thd, /*!< in/out: session */ | |
| 27330 | ib_log_level_t level, /*!< in: warning level */ | ||
| 27331 | uint32_t code, /*!< MySQL error code */ | ||
| 27332 | ...) /*!< Args */ | ||
| 27333 | { | ||
| 27334 | va_list args; | ||
| 27335 | 2887 | char *str = nullptr; | |
| 27336 |
1/2✓ Branch 0 taken 2887 times.
✗ Branch 1 not taken.
|
2887 | const char *format = innobase_get_err_msg(code); |
| 27337 | |||
| 27338 | /* If the caller wants to push a message to the client then | ||
| 27339 | the caller must pass a valid session handle. */ | ||
| 27340 | |||
| 27341 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2887 times.
|
2887 | ut_a(thd != nullptr); |
| 27342 | |||
| 27343 | /* The error code must exist in the messages_to_clients.txt file. */ | ||
| 27344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2887 times.
|
2887 | ut_a(format != nullptr); |
| 27345 | |||
| 27346 | 2887 | va_start(args, code); | |
| 27347 | |||
| 27348 | #ifdef _WIN32 | ||
| 27349 | int size = _vscprintf(format, args) + 1; | ||
| 27350 | if (size > 0) { | ||
| 27351 | str = static_cast<char *>(malloc(size)); | ||
| 27352 | } | ||
| 27353 | if (str == NULL) { | ||
| 27354 | va_end(args); | ||
| 27355 | return; /* Watch for Out-Of-Memory */ | ||
| 27356 | } | ||
| 27357 | str[size - 1] = 0x0; | ||
| 27358 | vsnprintf(str, size, format, args); | ||
| 27359 | #elif HAVE_VASPRINTF | ||
| 27360 | int ret; | ||
| 27361 | 2887 | ret = vasprintf(&str, format, args); | |
| 27362 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2887 times.
|
2887 | if (ret < 0) { |
| 27363 | ✗ | va_end(args); | |
| 27364 | ✗ | return; /* Watch for Out-Of-Memory */ | |
| 27365 | } | ||
| 27366 | #else | ||
| 27367 | /* Use a fixed length string. */ | ||
| 27368 | str = static_cast<char *>(malloc(BUFSIZ)); | ||
| 27369 | if (str == NULL) { | ||
| 27370 | va_end(args); | ||
| 27371 | return; /* Watch for Out-Of-Memory */ | ||
| 27372 | } | ||
| 27373 | vsnprintf(str, BUFSIZ, format, args); | ||
| 27374 | #endif /* _WIN32 */ | ||
| 27375 | |||
| 27376 | Sql_condition::enum_severity_level l; | ||
| 27377 | |||
| 27378 | 2887 | l = Sql_condition::SL_NOTE; | |
| 27379 | |||
| 27380 |
2/5✗ Branch 0 not taken.
✓ Branch 1 taken 2327 times.
✓ Branch 2 taken 560 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
2887 | switch (level) { |
| 27381 | ✗ | case IB_LOG_LEVEL_INFO: | |
| 27382 | ✗ | break; | |
| 27383 | 2327 | case IB_LOG_LEVEL_WARN: | |
| 27384 | 2327 | l = Sql_condition::SL_WARNING; | |
| 27385 | 2327 | break; | |
| 27386 | 560 | case IB_LOG_LEVEL_ERROR: | |
| 27387 | /* We can't use push_warning_printf(), it is a hard error. */ | ||
| 27388 |
1/2✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
|
560 | my_printf_error(code, "%s", MYF(0), str); |
| 27389 | 560 | break; | |
| 27390 | ✗ | case IB_LOG_LEVEL_FATAL: | |
| 27391 | ✗ | l = Sql_condition::SEVERITY_END; | |
| 27392 | ✗ | break; | |
| 27393 | #ifdef UNIV_HOTBACKUP | ||
| 27394 | default: | ||
| 27395 | break; | ||
| 27396 | #endif /* UNIV_HOTBACKUP */ | ||
| 27397 | } | ||
| 27398 | |||
| 27399 |
2/2✓ Branch 0 taken 2327 times.
✓ Branch 1 taken 560 times.
|
2887 | if (level != IB_LOG_LEVEL_ERROR) { |
| 27400 |
1/2✓ Branch 0 taken 2327 times.
✗ Branch 1 not taken.
|
2327 | push_warning_printf(thd, l, code, "InnoDB: %s", str); |
| 27401 | } | ||
| 27402 | |||
| 27403 | 2887 | va_end(args); | |
| 27404 | 2887 | free(str); | |
| 27405 | |||
| 27406 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2887 times.
|
2887 | if (level == IB_LOG_LEVEL_FATAL) { |
| 27407 | ✗ | ut_error; | |
| 27408 | } | ||
| 27409 | } | ||
| 27410 | |||
| 27411 | /** Use this when the args are first converted to a formatted string and then | ||
| 27412 | passed to the format string from messages_to_clients.txt. The error message | ||
| 27413 | format must be: "Some string ... %s". | ||
| 27414 | |||
| 27415 | Push a warning message to the client, it is a wrapper around: | ||
| 27416 | |||
| 27417 | void push_warning_printf( | ||
| 27418 | THD *thd, Sql_condition::enum_condition_level level, | ||
| 27419 | uint code, const char *format, ...); | ||
| 27420 | */ | ||
| 27421 | 305 | void ib_errf(THD *thd, /*!< in/out: session */ | |
| 27422 | ib_log_level_t level, /*!< in: warning level */ | ||
| 27423 | uint32_t code, /*!< MySQL error code */ | ||
| 27424 | const char *format, /*!< printf format */ | ||
| 27425 | ...) /*!< Args */ | ||
| 27426 | { | ||
| 27427 | 305 | char *str = nullptr; | |
| 27428 | va_list args; | ||
| 27429 | |||
| 27430 | /* If the caller wants to push a message to the client then | ||
| 27431 | the caller must pass a valid session handle. */ | ||
| 27432 | |||
| 27433 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
|
305 | ut_a(thd != nullptr); |
| 27434 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
|
305 | ut_a(format != nullptr); |
| 27435 | |||
| 27436 | 305 | va_start(args, format); | |
| 27437 | |||
| 27438 | #ifdef _WIN32 | ||
| 27439 | int size = _vscprintf(format, args) + 1; | ||
| 27440 | if (size > 0) { | ||
| 27441 | str = static_cast<char *>(malloc(size)); | ||
| 27442 | } | ||
| 27443 | if (str == NULL) { | ||
| 27444 | va_end(args); | ||
| 27445 | return; /* Watch for Out-Of-Memory */ | ||
| 27446 | } | ||
| 27447 | str[size - 1] = 0x0; | ||
| 27448 | vsnprintf(str, size, format, args); | ||
| 27449 | #elif HAVE_VASPRINTF | ||
| 27450 | int ret; | ||
| 27451 | 305 | ret = vasprintf(&str, format, args); | |
| 27452 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
|
305 | if (ret < 0) { |
| 27453 | ✗ | va_end(args); | |
| 27454 | ✗ | return; /* Watch for Out-Of-Memory */ | |
| 27455 | } | ||
| 27456 | #else | ||
| 27457 | /* Use a fixed length string. */ | ||
| 27458 | str = static_cast<char *>(malloc(BUFSIZ)); | ||
| 27459 | if (str == NULL) { | ||
| 27460 | va_end(args); | ||
| 27461 | return; /* Watch for Out-Of-Memory */ | ||
| 27462 | } | ||
| 27463 | vsnprintf(str, BUFSIZ, format, args); | ||
| 27464 | #endif /* _WIN32 */ | ||
| 27465 | |||
| 27466 |
1/2✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
|
305 | ib_senderrf(thd, level, code, str); |
| 27467 | |||
| 27468 | 305 | va_end(args); | |
| 27469 | 305 | free(str); | |
| 27470 | } | ||
| 27471 | #endif /* !UNIV_HOTBACKUP */ | ||
| 27472 | |||
| 27473 | /* Keep the first 16 characters as-is, since the url is sometimes used | ||
| 27474 | as an offset from this.*/ | ||
| 27475 | const char *TROUBLESHOOTING_MSG = "Please refer to " REFMAN | ||
| 27476 | "innodb-troubleshooting.html" | ||
| 27477 | " for how to resolve the issue."; | ||
| 27478 | |||
| 27479 | const char *TROUBLESHOOT_DATADICT_MSG = "Please refer to " REFMAN | ||
| 27480 | "innodb-troubleshooting-datadict.html" | ||
| 27481 | " for how to resolve the issue."; | ||
| 27482 | |||
| 27483 | const char *BUG_REPORT_MSG = | ||
| 27484 | "Submit a detailed bug report to http://bugs.mysql.com"; | ||
| 27485 | |||
| 27486 | const char *FORCE_RECOVERY_MSG = "Please refer to " REFMAN | ||
| 27487 | "forcing-innodb-recovery.html" | ||
| 27488 | " for information about forcing recovery."; | ||
| 27489 | |||
| 27490 | const char *ERROR_CREATING_MSG = | ||
| 27491 | "Please refer to " REFMAN "error-creating-innodb.html"; | ||
| 27492 | |||
| 27493 | const char *OPERATING_SYSTEM_ERROR_MSG = | ||
| 27494 | "Refer to your operating system documentation for operating" | ||
| 27495 | " system error code information."; | ||
| 27496 | |||
| 27497 | const char *FOREIGN_KEY_CONSTRAINTS_MSG = | ||
| 27498 | "Please refer to " REFMAN | ||
| 27499 | "create-table-foreign-keys.html" | ||
| 27500 | " for correct foreign key definition."; | ||
| 27501 | |||
| 27502 | const char *INNODB_PARAMETERS_MSG = | ||
| 27503 | "Please refer to " REFMAN "innodb-parameters.html"; | ||
| 27504 | |||
| 27505 | #ifndef UNIV_HOTBACKUP | ||
| 27506 | /********************************************************************** | ||
| 27507 | Converts an identifier from my_charset_filename to UTF-8 charset. | ||
| 27508 | @return result string length, as returned by strconvert() */ | ||
| 27509 | 527 | uint innobase_convert_to_filename_charset( | |
| 27510 | char *to, /* out: converted identifier */ | ||
| 27511 | const char *from, /* in: identifier to convert */ | ||
| 27512 | ulint len) /* in: length of 'to', in bytes */ | ||
| 27513 | { | ||
| 27514 | uint errors; | ||
| 27515 | 527 | CHARSET_INFO *cs_to = &my_charset_filename; | |
| 27516 | 527 | CHARSET_INFO *cs_from = system_charset_info; | |
| 27517 | |||
| 27518 | return (static_cast<uint>( | ||
| 27519 |
1/2✓ Branch 0 taken 527 times.
✗ Branch 1 not taken.
|
527 | strconvert(cs_from, from, cs_to, to, static_cast<size_t>(len), &errors))); |
| 27520 | } | ||
| 27521 | |||
| 27522 | /********************************************************************** | ||
| 27523 | Converts an identifier from my_charset_filename to UTF-8 charset. | ||
| 27524 | @return result string length, as returned by strconvert() */ | ||
| 27525 | 184 | uint innobase_convert_to_system_charset( | |
| 27526 | char *to, /* out: converted identifier */ | ||
| 27527 | const char *from, /* in: identifier to convert */ | ||
| 27528 | ulint len, /* in: length of 'to', in bytes */ | ||
| 27529 | uint *errors) /* out: error return */ | ||
| 27530 | { | ||
| 27531 | 184 | CHARSET_INFO *cs1 = &my_charset_filename; | |
| 27532 | 184 | CHARSET_INFO *cs2 = system_charset_info; | |
| 27533 | |||
| 27534 | return (static_cast<uint>( | ||
| 27535 | 184 | strconvert(cs1, from, cs2, to, static_cast<size_t>(len), errors))); | |
| 27536 | } | ||
| 27537 | |||
| 27538 | /********************************************************************** | ||
| 27539 | Issue a warning that the row is too big. */ | ||
| 27540 | 5 | void ib_warn_row_too_big(const dict_table_t *table) { | |
| 27541 | /* If prefix is true then a 768-byte prefix is stored | ||
| 27542 | locally for BLOB fields. */ | ||
| 27543 | 5 | const bool prefix = !dict_table_has_atomic_blobs(table); | |
| 27544 | |||
| 27545 | const ulint free_space = | ||
| 27546 | 5 | page_get_free_space_of_empty(table->flags & DICT_TF_COMPACT) / 2; | |
| 27547 | |||
| 27548 | 5 | THD *thd = current_thd; | |
| 27549 | |||
| 27550 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
|
5 | push_warning_printf( |
| 27551 | thd, Sql_condition::SL_WARNING, HA_ERR_TOO_BIG_ROW, | ||
| 27552 | "Row size too large (> %lu). Changing some columns to TEXT" | ||
| 27553 | " or BLOB %smay help. In current row format, BLOB prefix of" | ||
| 27554 | " %d bytes is stored inline.", | ||
| 27555 | free_space, | ||
| 27556 | prefix ? "or using ROW_FORMAT=DYNAMIC or" | ||
| 27557 | " ROW_FORMAT=COMPRESSED " | ||
| 27558 | : "", | ||
| 27559 | prefix ? DICT_MAX_FIXED_COL_LEN : 0); | ||
| 27560 | 5 | } | |
| 27561 | |||
| 27562 | /** Constructs fake dict_col_t describing column for foreign key type | ||
| 27563 | compatibility check from column description in Ha_fk_column_type form. | ||
| 27564 | |||
| 27565 | @note dict_col_t which is produced by this call is not valid for general | ||
| 27566 | purposes. | ||
| 27567 | @param[out] col dict_col_t filled by this function | ||
| 27568 | @param[in] fk_col_type foreign key type information */ | ||
| 27569 | 553374 | static void innodb_fill_fake_column_struct( | |
| 27570 | dict_col_t *col, const Ha_fk_column_type *fk_col_type) { | ||
| 27571 | ulint unsigned_type; | ||
| 27572 | ulint binary_type; | ||
| 27573 | ulint charset_no; | ||
| 27574 | |||
| 27575 | 1106748 | ulint mtype = get_innobase_type_from_mysql_dd_type( | |
| 27576 | 553374 | &unsigned_type, &binary_type, &charset_no, fk_col_type->type, | |
| 27577 |
1/2✓ Branch 0 taken 553374 times.
✗ Branch 1 not taken.
|
553374 | fk_col_type->field_charset, fk_col_type->is_unsigned); |
| 27578 | |||
| 27579 | /* Fake prtype only contains info which is relevant for foreign key | ||
| 27580 | type compatibility check, especially the info used in cmp_cols_are_equal. */ | ||
| 27581 | ulint fake_prtype = | ||
| 27582 |
1/2✓ Branch 0 taken 553374 times.
✗ Branch 1 not taken.
|
553374 | dtype_form_prtype(unsigned_type | binary_type, charset_no); |
| 27583 | |||
| 27584 | 1106748 | ulint col_len = calc_pack_length( | |
| 27585 | 553374 | fk_col_type->type, fk_col_type->char_length, fk_col_type->elements_count, | |
| 27586 | /* InnoDB always treats BIT as char. */ | ||
| 27587 |
1/2✓ Branch 0 taken 553374 times.
✗ Branch 1 not taken.
|
553374 | true, fk_col_type->numeric_scale, fk_col_type->is_unsigned); |
| 27588 | |||
| 27589 |
1/2✓ Branch 0 taken 553374 times.
✗ Branch 1 not taken.
|
553374 | dict_mem_fill_column_struct(col, 0 /* fake col_pos */, mtype, fake_prtype, |
| 27590 | col_len, true, UINT32_UNDEFINED, 0, 0); | ||
| 27591 | 553374 | } | |
| 27592 | |||
| 27593 | /** Check if types of child and parent columns in foreign key are compatible. | ||
| 27594 | |||
| 27595 | @param[in] child_column_type Child column type description. | ||
| 27596 | @param[in] parent_column_type Parent column type description. | ||
| 27597 | @param[in] check_charsets Indicates whether we need to check | ||
| 27598 | that charsets of string columns | ||
| 27599 | match. Which is true in most cases. | ||
| 27600 | |||
| 27601 | @return True if types are compatible, False if not. */ | ||
| 27602 | 276687 | static bool innodb_check_fk_column_compat( | |
| 27603 | const Ha_fk_column_type *child_column_type, | ||
| 27604 | const Ha_fk_column_type *parent_column_type, bool check_charsets) { | ||
| 27605 | 276687 | dict_col_t dict_child_col, dict_parent_col; | |
| 27606 | |||
| 27607 |
1/2✓ Branch 0 taken 276687 times.
✗ Branch 1 not taken.
|
276687 | innodb_fill_fake_column_struct(&dict_child_col, child_column_type); |
| 27608 |
1/2✓ Branch 0 taken 276687 times.
✗ Branch 1 not taken.
|
276687 | innodb_fill_fake_column_struct(&dict_parent_col, parent_column_type); |
| 27609 | |||
| 27610 | return ( | ||
| 27611 |
1/2✓ Branch 0 taken 276687 times.
✗ Branch 1 not taken.
|
553374 | cmp_cols_are_equal(&dict_child_col, &dict_parent_col, check_charsets)); |
| 27612 | } | ||
| 27613 | |||
| 27614 | 15589 | static bool innobase_check_reserved_file_name(handlerton *, const char *name) { | |
| 27615 | 15589 | CHARSET_INFO *ci = system_charset_info; | |
| 27616 | 15589 | size_t logname_size = strlen(log_pre_8_0_30::FILE_BASE_NAME); | |
| 27617 | |||
| 27618 | /* Name is smaller than reserved name */ | ||
| 27619 |
2/2✓ Branch 0 taken 14343 times.
✓ Branch 1 taken 1246 times.
|
15589 | if (strlen(name) < logname_size) { |
| 27620 | 14343 | return (false); | |
| 27621 | } | ||
| 27622 | /* Do case insensitive comparison for name. */ | ||
| 27623 |
1/2✓ Branch 0 taken 1271 times.
✗ Branch 1 not taken.
|
1271 | for (uint i = 0; i < logname_size; i++) { |
| 27624 |
3/6✓ Branch 0 taken 1271 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1271 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1271 times.
|
1271 | ut_ad(!my_isalpha(ci, log_pre_8_0_30::FILE_BASE_NAME[i]) || |
| 27625 | my_islower(ci, log_pre_8_0_30::FILE_BASE_NAME[i])); | ||
| 27626 | |||
| 27627 |
2/2✓ Branch 0 taken 1246 times.
✓ Branch 1 taken 25 times.
|
1271 | if (my_tolower(ci, name[i]) != log_pre_8_0_30::FILE_BASE_NAME[i]) { |
| 27628 | 1246 | return (false); | |
| 27629 | } | ||
| 27630 | } | ||
| 27631 | ✗ | return (true); | |
| 27632 | } | ||
| 27633 | #endif /* !UNIV_HOTBACKUP */ | ||
| 27634 |